     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47

    use core::marker::PhantomData;
    use core::ptr::NonNull;

    /// Models a reborrow of some unique reference, when you know that the reborrow
    /// and all its descendants (i.e., all pointers and references derived from it)
    /// will not be used any more at some point, after which you want to use the
    /// original unique reference again.
    ///
    /// The borrow checker usually handles this stacking of borrows for you, but
    /// some control flows that accomplish this stacking are too complicated for
    /// the compiler to follow. A `DormantMutRef` allows you to check borrowing
    /// yourself, while still expressing its stacked nature, and encapsulating
    /// the raw pointer code needed to do this without undefined behavior.
    pub struct DormantMutRef<'a, T> {
        ptr: NonNull<T>,
        _marker: PhantomData<&'a mut T>,
    }

    unsafe impl<'a, T> Sync for DormantMutRef<'a, T> where &'a mut T: Sync {}
    unsafe impl<'a, T> Send for DormantMutRef<'a, T> where &'a mut T: Send {}

    impl<'a, T> DormantMutRef<'a, T> {
        /// Capture a unique borrow, and immediately reborrow it. For the compiler,
        /// the lifetime of the new reference is the same as the lifetime of the
        /// original reference, but you promise to use it for a shorter period.
        pub fn new(t: &'a mut T) -> (&'a mut T, Self) {
            let ptr = NonNull::from(t);
            // SAFETY: we hold the borrow throughout 'a via `_marker`, and we expose
            // only this reference, so it is unique.
            let new_ref = unsafe { &mut *ptr.as_ptr() };
            (new_ref, Self { ptr, _marker: PhantomData })
        }

        /// Revert to the unique borrow initially captured.
        ///
        /// # Safety
        ///
        /// The reborrow must have ended, i.e., the reference returned by `new` and
        /// all pointers and references derived from it, must not be used anymore.
        pub unsafe fn awaken(self) -> &'a mut T {
            // SAFETY: our own safety conditions imply this reference is again unique.
            unsafe { &mut *self.ptr.as_ptr() }
        }
    }

    #[cfg(test)]
    mod tests;