From 0d1ceb8cc3ff7fadf6f2aa15bd0bf4c7f1c72e09 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Wed, 18 Nov 2020 18:19:38 +0100 Subject: [PATCH] BTreeMap: bundle the duplication of node references in navigate.rs --- .../alloc/src/collections/btree/navigate.rs | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/library/alloc/src/collections/btree/navigate.rs b/library/alloc/src/collections/btree/navigate.rs index 17b4689e4a0ee..66bfaf9617d2a 100644 --- a/library/alloc/src/collections/btree/navigate.rs +++ b/library/alloc/src/collections/btree/navigate.rs @@ -130,6 +130,16 @@ fn full_range( } } +impl NodeRef { + /// Duplicates a NodeRef, even for a non-immutable borrow type. + /// # Safety + /// Never visit the same KV twice, and never end up with overlapping + /// value references. + unsafe fn fork(self) -> (Self, Self) { + unsafe { (ptr::read(&self), self) } + } +} + impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { /// Creates a pair of leaf edges delimiting a specified range in or underneath a node. /// @@ -180,10 +190,8 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> K: Borrow, R: RangeBounds, { - // We duplicate the root NodeRef here -- we will never visit the same KV - // twice, and never end up with overlapping value references. - let self2 = unsafe { ptr::read(&self) }; - range_search(self, self2, range) + let (self1, self2) = unsafe { self.fork() }; + range_search(self1, self2, range) } /// Splits a unique reference into a pair of leaf edges delimiting the full range of the tree. @@ -195,10 +203,8 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> Handle, K, V, marker::Leaf>, marker::Edge>, Handle, K, V, marker::Leaf>, marker::Edge>, ) { - // We duplicate the root NodeRef here -- we will never visit the same KV - // twice, and never end up with overlapping value references. - let self2 = unsafe { ptr::read(&self) }; - full_range(self, self2) + let (self1, self2) = unsafe { self.fork() }; + full_range(self1, self2) } } @@ -212,10 +218,8 @@ impl NodeRef { Handle, marker::Edge>, Handle, marker::Edge>, ) { - // We duplicate the root NodeRef here -- we will never access it in a way - // that overlaps references obtained from the root. - let self2 = unsafe { ptr::read(&self) }; - full_range(self, self2) + let (self1, self2) = unsafe { self.fork() }; + full_range(self1, self2) } }