Skip to content

Commit 7907345

Browse files
committed
Auto merge of rust-lang#81217 - ssomers:btree_bring_back_the_slice, r=Mark-Simulacrum
BTreeMap: bring back the key slice for immutable lookup Pave the way for binary search, by reverting a bit of rust-lang#73971, which banned `keys` for misbehaving while it was defined for every `BorrowType`. Adding some `debug_assert`s along the way. r? `@Mark-Simulacrum`
2 parents 1483e67 + c0e8075 commit 7907345

File tree

3 files changed

+23
-43
lines changed

3 files changed

+23
-43
lines changed

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

+18-25
Original file line numberDiff line numberDiff line change
@@ -238,13 +238,12 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
238238
/// such restrictions:
239239
/// - For each type parameter, we can only define a method either generically
240240
/// or for one particular type. For example, we cannot define a method like
241-
/// `key_at` generically for all `BorrowType`, because we want it to return
242-
/// `&'a K` for most choices of `BorrowType`, but plain `K` for `Owned`.
243-
/// We cannot define `key_at` once for all types that carry a lifetime.
241+
/// `into_kv` generically for all `BorrowType`, or once for all types that
242+
/// carry a lifetime, because we want it to return `&'a` references.
244243
/// Therefore, we define it only for the least powerful type `Immut<'a>`.
245244
/// - We cannot get implicit coercion from say `Mut<'a>` to `Immut<'a>`.
246245
/// Therefore, we have to explicitly call `reborrow` on a more powerfull
247-
/// `NodeRef` in order to reach a method like `key_at`.
246+
/// `NodeRef` in order to reach a method like `into_kv`.
248247
///
249248
/// All methods on `NodeRef` that return some kind of reference, either:
250249
/// - Take `self` by value, and return the lifetime carried by `BorrowType`.
@@ -344,26 +343,6 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
344343
}
345344
}
346345

347-
impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
348-
/// Exposes one of the keys stored in the node.
349-
///
350-
/// # Safety
351-
/// The node has more than `idx` initialized elements.
352-
pub unsafe fn key_at(self, idx: usize) -> &'a K {
353-
debug_assert!(idx < self.len());
354-
unsafe { self.into_leaf().keys.get_unchecked(idx).assume_init_ref() }
355-
}
356-
357-
/// Exposes one of the values stored in the node.
358-
///
359-
/// # Safety
360-
/// The node has more than `idx` initialized elements.
361-
unsafe fn val_at(self, idx: usize) -> &'a V {
362-
debug_assert!(idx < self.len());
363-
unsafe { self.into_leaf().vals.get_unchecked(idx).assume_init_ref() }
364-
}
365-
}
366-
367346
impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
368347
/// Finds the parent of the current node. Returns `Ok(handle)` if the current
369348
/// node actually has a parent, where `handle` points to the edge of the parent
@@ -421,6 +400,14 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
421400
// SAFETY: there can be no mutable references into this tree borrowed as `Immut`.
422401
unsafe { &*ptr }
423402
}
403+
404+
/// Borrows a view into the keys stored in the node.
405+
pub fn keys(&self) -> &[K] {
406+
let leaf = self.into_leaf();
407+
unsafe {
408+
MaybeUninit::slice_assume_init_ref(leaf.keys.get_unchecked(..usize::from(leaf.len)))
409+
}
410+
}
424411
}
425412

426413
impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
@@ -987,7 +974,11 @@ impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::Internal>, marke
987974

988975
impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Immut<'a>, K, V, NodeType>, marker::KV> {
989976
pub fn into_kv(self) -> (&'a K, &'a V) {
990-
(unsafe { self.node.key_at(self.idx) }, unsafe { self.node.val_at(self.idx) })
977+
debug_assert!(self.idx < self.node.len());
978+
let leaf = self.node.into_leaf();
979+
let k = unsafe { leaf.keys.get_unchecked(self.idx).assume_init_ref() };
980+
let v = unsafe { leaf.vals.get_unchecked(self.idx).assume_init_ref() };
981+
(k, v)
991982
}
992983
}
993984

@@ -997,6 +988,7 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>
997988
}
998989

999990
pub fn into_val_mut(self) -> &'a mut V {
991+
debug_assert!(self.idx < self.node.len());
1000992
let leaf = self.node.into_leaf_mut();
1001993
unsafe { leaf.vals.get_unchecked_mut(self.idx).assume_init_mut() }
1002994
}
@@ -1010,6 +1002,7 @@ impl<'a, K, V, NodeType> Handle<NodeRef<marker::ValMut<'a>, K, V, NodeType>, mar
10101002

10111003
impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::KV> {
10121004
pub fn kv_mut(&mut self) -> (&mut K, &mut V) {
1005+
debug_assert!(self.idx < self.node.len());
10131006
// We cannot call separate key and value methods, because calling the second one
10141007
// invalidates the reference returned by the first.
10151008
unsafe {

library/alloc/src/collections/btree/node/tests.rs

+1-11
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,7 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>
2929
navigate::Position::Leaf(leaf) => {
3030
let depth = self.height();
3131
let indent = " ".repeat(depth);
32-
result += &format!("\n{}", indent);
33-
if leaf.len() == 0 {
34-
result += "(empty node)";
35-
} else {
36-
for idx in 0..leaf.len() {
37-
if idx > 0 {
38-
result += ", ";
39-
}
40-
result += &format!("{:?}", unsafe { leaf.key_at(idx) });
41-
}
42-
}
32+
result += &format!("\n{}{:?}", indent, leaf.keys());
4333
}
4434
navigate::Position::Internal(_) => {}
4535
navigate::Position::InternalKV(kv) => {

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

+4-7
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,15 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
7171
Q: Ord,
7272
K: Borrow<Q>,
7373
{
74-
// This function is defined over all borrow types (immutable, mutable, owned).
75-
// Using `keys_at()` is fine here even if BorrowType is mutable, as all we return
76-
// is an index -- not a reference.
77-
let len = self.len();
78-
for i in 0..len {
79-
let k = unsafe { self.reborrow().key_at(i) };
74+
let node = self.reborrow();
75+
let keys = node.keys();
76+
for (i, k) in keys.iter().enumerate() {
8077
match key.cmp(k.borrow()) {
8178
Ordering::Greater => {}
8279
Ordering::Equal => return IndexResult::KV(i),
8380
Ordering::Less => return IndexResult::Edge(i),
8481
}
8582
}
86-
IndexResult::Edge(len)
83+
IndexResult::Edge(keys.len())
8784
}
8885
}

0 commit comments

Comments
 (0)