]>
Commit | Line | Data |
---|---|---|
dfeec247 | 1 | use rustc_data_structures::sync::{MappedReadGuard, ReadGuard, RwLock}; |
7cac9316 XL |
2 | |
3 | /// The `Steal` struct is intended to used as the value for a query. | |
4 | /// Specifically, we sometimes have queries (*cough* MIR *cough*) | |
5 | /// where we create a large, complex value that we want to iteratively | |
6 | /// update (e.g., optimize). We could clone the value for each | |
7 | /// optimization, but that'd be expensive. And yet we don't just want | |
8 | /// to mutate it in place, because that would spoil the idea that | |
9 | /// queries are these pure functions that produce an immutable value | |
dc9dc135 XL |
10 | /// (since if you did the query twice, you could observe the mutations). |
11 | /// So instead we have the query produce a `&'tcx Steal<mir::Body<'tcx>>` | |
12 | /// (to be very specific). Now we can read from this | |
7cac9316 XL |
13 | /// as much as we want (using `borrow()`), but you can also |
14 | /// `steal()`. Once you steal, any further attempt to read will panic. | |
9fa01778 | 15 | /// Therefore, we know that -- assuming no ICE -- nobody is observing |
7cac9316 XL |
16 | /// the fact that the MIR was updated. |
17 | /// | |
18 | /// Obviously, whenever you have a query that yields a `Steal` value, | |
19 | /// you must treat it with caution, and make sure that you know that | |
20 | /// -- once the value is stolen -- it will never be read from again. | |
9fa01778 XL |
21 | // |
22 | // FIXME(#41710): what is the best way to model linear queries? | |
7cac9316 | 23 | pub struct Steal<T> { |
dfeec247 | 24 | value: RwLock<Option<T>>, |
7cac9316 XL |
25 | } |
26 | ||
27 | impl<T> Steal<T> { | |
28 | pub fn new(value: T) -> Self { | |
dfeec247 | 29 | Steal { value: RwLock::new(Some(value)) } |
7cac9316 XL |
30 | } |
31 | ||
0bf4aa26 | 32 | pub fn borrow(&self) -> MappedReadGuard<'_, T> { |
83c7162d | 33 | ReadGuard::map(self.value.borrow(), |opt| match *opt { |
7cac9316 | 34 | None => bug!("attempted to read from stolen value"), |
dfeec247 | 35 | Some(ref v) => v, |
7cac9316 XL |
36 | }) |
37 | } | |
38 | ||
39 | pub fn steal(&self) -> T { | |
83c7162d | 40 | let value_ref = &mut *self.value.try_write().expect("stealing value which is locked"); |
a1dfa0c6 | 41 | let value = value_ref.take(); |
7cac9316 XL |
42 | value.expect("attempt to read from stolen value") |
43 | } | |
44 | } |