1 use std::cell::UnsafeCell; 2 use std::mem; 3 4 // Like `&mut *x.get()`, but without intermediate raw pointers. 5 #[allow(mutable_transmutes)] unsafe_cell_get<T>(x: &UnsafeCell<T>) -> &'static mut T6unsafe fn unsafe_cell_get<T>(x: &UnsafeCell<T>) -> &'static mut T { 7 mem::transmute(x) 8 } 9 main()10fn main() { unsafe { 11 let c = &UnsafeCell::new(UnsafeCell::new(0)); 12 let inner_uniq = &mut *c.get(); 13 let inner_shr = &*inner_uniq; 14 // stack: [c: SharedReadWrite, inner_uniq: Unique, inner_shr: SharedReadWrite] 15 16 let _val = c.get().read(); // invalidates inner_uniq 17 // stack: [c: SharedReadWrite, inner_uniq: Disabled, inner_shr: SharedReadWrite] 18 19 // We have to be careful not to add any raw pointers above inner_uniq in 20 // the stack, hence the use of unsafe_cell_get. 21 let _val = *unsafe_cell_get(inner_shr); // this still works 22 23 *c.get() = UnsafeCell::new(0); // now inner_shr gets invalidated 24 // stack: [c: SharedReadWrite] 25 26 // now this does not work any more 27 let _val = *inner_shr.get(); //~ ERROR borrow stack 28 } } 29