1 use core::marker::PhantomData; 2 use core::ptr::NonNull; 3 4 /// Models a reborrow of some unique reference, when you know that the reborrow 5 /// and all its descendants (i.e., all pointers and references derived from it) 6 /// will not be used any more at some point, after which you want to use the 7 /// original unique reference again. 8 /// 9 /// The borrow checker usually handles this stacking of borrows for you, but 10 /// some control flows that accomplish this stacking are too complicated for 11 /// the compiler to follow. A `DormantMutRef` allows you to check borrowing 12 /// yourself, while still expressing its stacked nature, and encapsulating 13 /// the raw pointer code needed to do this without undefined behavior. 14 pub struct DormantMutRef<'a, T> { 15 ptr: NonNull<T>, 16 _marker: PhantomData<&'a mut T>, 17 } 18 19 unsafe impl<'a, T> Sync for DormantMutRef<'a, T> where &'a mut T: Sync {} 20 unsafe impl<'a, T> Send for DormantMutRef<'a, T> where &'a mut T: Send {} 21 22 impl<'a, T> DormantMutRef<'a, T> { 23 /// Capture a unique borrow, and immediately reborrow it. For the compiler, 24 /// the lifetime of the new reference is the same as the lifetime of the 25 /// original reference, but you promise to use it for a shorter period. new(t: &'a mut T) -> (&'a mut T, Self)26 pub fn new(t: &'a mut T) -> (&'a mut T, Self) { 27 let ptr = NonNull::from(t); 28 // SAFETY: we hold the borrow throughout 'a via `_marker`, and we expose 29 // only this reference, so it is unique. 30 let new_ref = unsafe { &mut *ptr.as_ptr() }; 31 (new_ref, Self { ptr, _marker: PhantomData }) 32 } 33 34 /// Revert to the unique borrow initially captured. 35 /// 36 /// # Safety 37 /// 38 /// The reborrow must have ended, i.e., the reference returned by `new` and 39 /// all pointers and references derived from it, must not be used anymore. awaken(self) -> &'a mut T40 pub unsafe fn awaken(self) -> &'a mut T { 41 // SAFETY: our own safety conditions imply this reference is again unique. 42 unsafe { &mut *self.ptr.as_ptr() } 43 } 44 45 /// Borrows a new mutable reference from the unique borrow initially captured. 46 /// 47 /// # Safety 48 /// 49 /// The reborrow must have ended, i.e., the reference returned by `new` and 50 /// all pointers and references derived from it, must not be used anymore. reborrow(&mut self) -> &'a mut T51 pub unsafe fn reborrow(&mut self) -> &'a mut T { 52 // SAFETY: our own safety conditions imply this reference is again unique. 53 unsafe { &mut *self.ptr.as_ptr() } 54 } 55 56 /// Borrows a new shared reference from the unique borrow initially captured. 57 /// 58 /// # Safety 59 /// 60 /// The reborrow must have ended, i.e., the reference returned by `new` and 61 /// all pointers and references derived from it, must not be used anymore. reborrow_shared(&self) -> &'a T62 pub unsafe fn reborrow_shared(&self) -> &'a T { 63 // SAFETY: our own safety conditions imply this reference is again unique. 64 unsafe { &*self.ptr.as_ptr() } 65 } 66 } 67 68 #[cfg(test)] 69 mod tests; 70