summaryrefslogtreecommitdiffstats
path: root/library/alloc/src/collections/btree/borrow.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /library/alloc/src/collections/btree/borrow.rs
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/alloc/src/collections/btree/borrow.rs')
-rw-r--r--library/alloc/src/collections/btree/borrow.rs47
1 files changed, 47 insertions, 0 deletions
diff --git a/library/alloc/src/collections/btree/borrow.rs b/library/alloc/src/collections/btree/borrow.rs
new file mode 100644
index 000000000..016f139a5
--- /dev/null
+++ b/library/alloc/src/collections/btree/borrow.rs
@@ -0,0 +1,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;