Skip to content

Commit cbab347

Browse files
committed
Auto merge of rust-lang#79376 - ssomers:btree_choose_parent_kv, r=Mark-Simulacrum
BTreeMap: clarify comments and panics around choose_parent_kv Fixes a lie in recent code: `unreachable!("empty non-root node")` should shout "empty internal node", but it might as well be good and keep quiet r? `@Mark-Simulacrum`
2 parents 057937b + 5057642 commit cbab347

File tree

2 files changed

+14
-12
lines changed

2 files changed

+14
-12
lines changed

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

+8-6
Original file line numberDiff line numberDiff line change
@@ -1288,30 +1288,32 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
12881288
/// Chooses a balancing context involving the node as a child, thus between
12891289
/// the KV immediately to the left or to the right in the parent node.
12901290
/// Returns an `Err` if there is no parent.
1291+
/// Panics if the parent is empty.
12911292
///
1292-
/// This method optimizes for a node that has fewer elements than its left
1293-
/// and right siblings, if they exist, by preferring the left parent KV.
1294-
/// Merging with the left sibling is faster, since we only need to move
1293+
/// Prefers the left side, to be optimal if the given node is somehow
1294+
/// underfull, meaning here only that it has fewer elements than its left
1295+
/// sibling and than its right sibling, if they exist. In that case,
1296+
/// merging with the left sibling is faster, since we only need to move
12951297
/// the node's N elements, instead of shifting them to the right and moving
12961298
/// more than N elements in front. Stealing from the left sibling is also
12971299
/// typically faster, since we only need to shift the node's N elements to
12981300
/// the right, instead of shifting at least N of the sibling's elements to
12991301
/// the left.
13001302
pub fn choose_parent_kv(self) -> Result<LeftOrRight<BalancingContext<'a, K, V>>, Self> {
13011303
match unsafe { ptr::read(&self) }.ascend() {
1302-
Ok(parent) => match parent.left_kv() {
1304+
Ok(parent_edge) => match parent_edge.left_kv() {
13031305
Ok(left_parent_kv) => Ok(LeftOrRight::Left(BalancingContext {
13041306
parent: unsafe { ptr::read(&left_parent_kv) },
13051307
left_child: left_parent_kv.left_edge().descend(),
13061308
right_child: self,
13071309
})),
1308-
Err(parent) => match parent.right_kv() {
1310+
Err(parent_edge) => match parent_edge.right_kv() {
13091311
Ok(right_parent_kv) => Ok(LeftOrRight::Right(BalancingContext {
13101312
parent: unsafe { ptr::read(&right_parent_kv) },
13111313
left_child: self,
13121314
right_child: right_parent_kv.right_edge().descend(),
13131315
})),
1314-
Err(_) => unreachable!("empty non-root node"),
1316+
Err(_) => unreachable!("empty internal node"),
13151317
},
13161318
},
13171319
Err(root) => Err(root),

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

+6-6
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,12 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
5454
pos = unsafe { new_pos.cast_to_leaf_unchecked() };
5555

5656
// Only if we merged, the parent (if any) has shrunk, but skipping
57-
// the following step does not pay off in benchmarks.
57+
// the following step otherwise does not pay off in benchmarks.
5858
//
5959
// SAFETY: We won't destroy or rearrange the leaf where `pos` is at
6060
// by handling its parent recursively; at worst we will destroy or
6161
// rearrange the parent through the grandparent, thus change the
62-
// leaf's parent pointer.
62+
// link to the parent inside the leaf.
6363
if let Ok(parent) = unsafe { pos.reborrow_mut() }.into_node().ascend() {
6464
parent.into_node().handle_shrunk_node_recursively(handle_emptied_internal_root);
6565
}
@@ -90,8 +90,8 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>,
9090
}
9191

9292
impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
93-
/// Stocks up a possibly underfull internal node, recursively.
94-
/// Climbs up until it reaches an ancestor that has elements to spare or the root.
93+
/// Stocks up a possibly underfull internal node and its ancestors,
94+
/// until it reaches an ancestor that has elements to spare or is the root.
9595
fn handle_shrunk_node_recursively<F: FnOnce()>(mut self, handle_emptied_internal_root: F) {
9696
loop {
9797
self = match self.len() {
@@ -122,7 +122,7 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
122122
) -> Option<NodeRef<marker::Mut<'a>, K, V, marker::Internal>> {
123123
match self.forget_type().choose_parent_kv() {
124124
Ok(Left(left_parent_kv)) => {
125-
debug_assert!(left_parent_kv.right_child_len() == MIN_LEN - 1);
125+
debug_assert_eq!(left_parent_kv.right_child_len(), MIN_LEN - 1);
126126
if left_parent_kv.can_merge() {
127127
let pos = left_parent_kv.merge(None);
128128
let parent_edge = unsafe { unwrap_unchecked(pos.into_node().ascend().ok()) };
@@ -134,7 +134,7 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
134134
}
135135
}
136136
Ok(Right(right_parent_kv)) => {
137-
debug_assert!(right_parent_kv.left_child_len() == MIN_LEN - 1);
137+
debug_assert_eq!(right_parent_kv.left_child_len(), MIN_LEN - 1);
138138
if right_parent_kv.can_merge() {
139139
let pos = right_parent_kv.merge(None);
140140
let parent_edge = unsafe { unwrap_unchecked(pos.into_node().ascend().ok()) };

0 commit comments

Comments
 (0)