-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BTreeMap: pull the map's root out of NodeRef
- Loading branch information
Showing
5 changed files
with
163 additions
and
117 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
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>, | ||
} | ||
|
||
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
use super::DormantMutRef; | ||
|
||
#[test] | ||
fn test_borrow() { | ||
let mut data = 1; | ||
let mut stack = vec![]; | ||
let mut rr = &mut data; | ||
for factor in [2, 3, 7].iter() { | ||
let (r, dormant_r) = DormantMutRef::new(rr); | ||
rr = r; | ||
assert_eq!(*rr, 1); | ||
stack.push((factor, dormant_r)); | ||
} | ||
while let Some((factor, dormant_r)) = stack.pop() { | ||
let r = unsafe { dormant_r.awaken() }; | ||
*r *= factor; | ||
} | ||
assert_eq!(data, 42); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
mod borrow; | ||
pub mod map; | ||
mod navigate; | ||
mod node; | ||
|
Oops, something went wrong.