alloc/collections/btree/
borrow.rs

1use core::marker::PhantomData;
2use 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.
14pub(super) struct DormantMutRef<'a, T> {
15    ptr: NonNull<T>,
16    _marker: PhantomData<&'a mut T>,
17}
18
19unsafe impl<'a, T> Sync for DormantMutRef<'a, T> where &'a mut T: Sync {}
20unsafe impl<'a, T> Send for DormantMutRef<'a, T> where &'a mut T: Send {}
21
22impl<'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.
26    pub(super) 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.
40    pub(super) 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.
51    pub(super) 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.
62    pub(super) 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)]
69mod tests;