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. |
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. |
40 | 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. |
51 | 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. |
62 | 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 | |