diff --git a/compiler/rustc_data_structures/src/steal.rs b/compiler/rustc_data_structures/src/steal.rs index 0d79d98b5d966..afa9bc36f2c5e 100644 --- a/compiler/rustc_data_structures/src/steal.rs +++ b/compiler/rustc_data_structures/src/steal.rs @@ -1,5 +1,5 @@ use crate::stable_hasher::{HashStable, StableHasher}; -use crate::sync::{MappedReadGuard, ReadGuard, RwLock}; +use crate::sync::{MappedReadGuard, MappedWriteGuard, ReadGuard, RwLock, WriteGuard}; /// The `Steal` struct is intended to used as the value for a query. /// Specifically, we sometimes have queries (*cough* MIR *cough*) @@ -40,9 +40,17 @@ impl Steal { ReadGuard::map(borrow, |opt| opt.as_ref().unwrap()) } + /// An escape hatch for rustc drivers to mutate `Steal` caches. + /// + /// Use at your own risk. This can badly break incremental compilation + /// and anything else that relies on the immutability of query caches. #[track_caller] - pub fn get_mut(&mut self) -> &mut T { - self.value.get_mut().as_mut().expect("attempt to read from stolen value") + pub fn risky_hack_borrow_mut(&self) -> MappedWriteGuard<'_, T> { + let borrow = self.value.borrow_mut(); + if borrow.is_none() { + panic!("attempted to read from stolen value: {}", std::any::type_name::()); + } + WriteGuard::map(borrow, |opt| opt.as_mut().unwrap()) } #[track_caller]