1
1
use std:: cell:: { Ref , RefCell } ;
2
2
use std:: mem;
3
3
4
+ /// The `Steal` struct is intended to used as the value for a query.
5
+ /// Specifically, we sometimes have queries (*cough* MIR *cough*)
6
+ /// where we create a large, complex value that we want to iteratively
7
+ /// update (e.g., optimize). We could clone the value for each
8
+ /// optimization, but that'd be expensive. And yet we don't just want
9
+ /// to mutate it in place, because that would spoil the idea that
10
+ /// queries are these pure functions that produce an immutable value
11
+ /// (since if you did the query twice, you could observe the
12
+ /// mutations). So instead we have the query produce a `&'tcx
13
+ /// Steal<Mir<'tcx>>` (to be very specific). Now we can read from this
14
+ /// as much as we want (using `borrow()`), but you can also
15
+ /// `steal()`. Once you steal, any further attempt to read will panic.
16
+ /// Therefore we know that -- assuming no ICE -- nobody is observing
17
+ /// the fact that the MIR was updated.
18
+ ///
19
+ /// Obviously, whenever you have a query that yields a `Steal` value,
20
+ /// you must treat it with caution, and make sure that you know that
21
+ /// -- once the value is stolen -- it will never be read from again.
4
22
pub struct Steal < T > {
5
23
value : RefCell < Option < T > >
6
24
}
@@ -14,7 +32,7 @@ impl<T> Steal<T> {
14
32
15
33
pub fn borrow ( & self ) -> Ref < T > {
16
34
Ref :: map ( self . value . borrow ( ) , |opt| match * opt {
17
- None => panic ! ( "attempted to read from stolen value" ) ,
35
+ None => bug ! ( "attempted to read from stolen value" ) ,
18
36
Some ( ref v) => v
19
37
} )
20
38
}
0 commit comments