Skip to content

Commit b4c2e2f

Browse files
committed
BTreeMap: clean up the full_range function
1 parent d1aed50 commit b4c2e2f

File tree

1 file changed

+36
-32
lines changed

1 file changed

+36
-32
lines changed

library/alloc/src/collections/btree/navigate.rs

+36-32
Original file line numberDiff line numberDiff line change
@@ -104,34 +104,39 @@ where
104104
}
105105
}
106106

107-
/// Equivalent to `range_search(k, v, ..)` but without the `Ord` bound.
108-
fn full_range<BorrowType, K, V>(
109-
root1: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
110-
root2: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
111-
) -> (
112-
Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
113-
Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
114-
) {
115-
let mut min_node = root1;
116-
let mut max_node = root2;
117-
loop {
118-
let front = min_node.first_edge();
119-
let back = max_node.last_edge();
120-
match (front.force(), back.force()) {
121-
(Leaf(f), Leaf(b)) => {
122-
return (f, b);
107+
/// Equivalent to `range_search(self, self, ..)` but without the `Ord` bound.
108+
/// Equivalent to `(self.first_leaf_edge(), self.last_leaf_edge())` but
109+
/// duplicating `self` and more efficient.
110+
/// # Safety
111+
/// - Do not expose for `BorrowType` `Mut`, because one handle could destroy the
112+
/// edge or node referred to by the other.
113+
/// - Unless `BorrowType` is `Immut`, do not use the two handles to visit the
114+
/// same KV twice.
115+
impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
116+
unsafe fn find_leaf_edges_spanning_tree(
117+
self,
118+
) -> (
119+
Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
120+
Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
121+
) {
122+
match self.force() {
123+
Leaf(root1) => {
124+
let root2 = unsafe { ptr::read(&root1) };
125+
return (root1.first_edge(), root2.last_edge());
123126
}
124-
(Internal(min_int), Internal(max_int)) => {
125-
min_node = min_int.descend();
126-
max_node = max_int.descend();
127+
Internal(root1) => {
128+
let root2 = unsafe { ptr::read(&root1) };
129+
// Read both ends of the edges array jointly.
130+
let first_child = root1.first_edge().descend();
131+
let last_child = root2.last_edge().descend();
132+
(first_child.first_leaf_edge(), last_child.last_leaf_edge())
127133
}
128-
_ => unreachable!("BTreeMap has different depths"),
129-
};
134+
}
130135
}
131136
}
132137

133138
impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal> {
134-
/// Creates a pair of leaf edges delimiting a specified range in or underneath a node.
139+
/// Finds the pair of leaf edges delimiting a specified range in the tree.
135140
///
136141
/// The result is meaningful only if the tree is ordered by key, like the tree
137142
/// in a `BTreeMap` is.
@@ -150,14 +155,15 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>
150155
range_search(self, self, range)
151156
}
152157

153-
/// Returns (self.first_leaf_edge(), self.last_leaf_edge()), but more efficiently.
158+
/// Finds the pair of leaf edges delimiting the entire tree.
154159
pub fn full_range(
155160
self,
156161
) -> (
157162
Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>,
158163
Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>,
159164
) {
160-
full_range(self, self)
165+
// SAFETY: our borrow type is `Immut`.
166+
unsafe { self.find_leaf_edges_spanning_tree() }
161167
}
162168
}
163169

@@ -195,10 +201,9 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::ValMut<'a>, K, V, marker::LeafOrInternal>
195201
Handle<NodeRef<marker::ValMut<'a>, K, V, marker::Leaf>, marker::Edge>,
196202
Handle<NodeRef<marker::ValMut<'a>, K, V, marker::Leaf>, marker::Edge>,
197203
) {
198-
// We duplicate the root NodeRef here -- we will never visit the same KV
199-
// twice, and never end up with overlapping value references.
200-
let self2 = unsafe { ptr::read(&self) };
201-
full_range(self, self2)
204+
// SAFETY: we will never visit the same KV twice,
205+
// and never end up with overlapping value references.
206+
unsafe { self.find_leaf_edges_spanning_tree() }
202207
}
203208
}
204209

@@ -212,10 +217,9 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
212217
Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>,
213218
Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>,
214219
) {
215-
// We duplicate the root NodeRef here -- we will never access it in a way
216-
// that overlaps references obtained from the root.
217-
let self2 = unsafe { ptr::read(&self) };
218-
full_range(self, self2)
220+
// SAFETY: we will never visit the same KV twice,
221+
// because we only visit any KV to drop it.
222+
unsafe { self.find_leaf_edges_spanning_tree() }
219223
}
220224
}
221225

0 commit comments

Comments
 (0)