Skip to content

Commit f5230fb

Browse files
committedNov 16, 2020
Auto merge of #78631 - ssomers:btree-alias_for_underfull, r=Mark-Simulacrum
BTreeMap: fix pointer provenance rules in underfullness Continuing on #78480, and for readability, and possibly for performance: avoid aliasing when handling underfull nodes, and consolidate the code doing that. In particular: - Avoid the rather explicit aliasing for internal nodes in `remove_kv_tracking`. - Climb down to the root to handle underfull nodes using a reborrowed handle, rather than one copied with `ptr::read`, before resuming on the leaf level. - Integrate the code tracking leaf edge position into the functions performing changes, rather than bolting it on. r? `@Mark-Simulacrum`
2 parents f4d014c + 4cfa5bd commit f5230fb

File tree

7 files changed

+320
-203
lines changed

7 files changed

+320
-203
lines changed
 

‎library/alloc/src/collections/btree/append.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -89,20 +89,15 @@ impl<K, V> Root<K, V> {
8989
let mut cur_node = self.node_as_mut();
9090
while let Internal(internal) = cur_node.force() {
9191
// Check if right-most child is underfull.
92-
let mut last_edge = internal.last_edge();
93-
let right_child_len = last_edge.reborrow().descend().len();
92+
let mut last_kv = internal.last_kv().consider_for_balancing();
93+
let right_child_len = last_kv.right_child_len();
9494
if right_child_len < MIN_LEN {
9595
// We need to steal.
96-
let mut last_kv = match last_edge.left_kv() {
97-
Ok(left) => left,
98-
Err(_) => unreachable!(),
99-
};
10096
last_kv.bulk_steal_left(MIN_LEN - right_child_len);
101-
last_edge = last_kv.right_edge();
10297
}
10398

10499
// Go further down.
105-
cur_node = last_edge.descend();
100+
cur_node = last_kv.into_right_child();
106101
}
107102
}
108103
}

‎library/alloc/src/collections/btree/mem.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use core::ptr;
66
/// relevant function.
77
///
88
/// If a panic occurs in the `change` closure, the entire process will be aborted.
9+
#[allow(dead_code)] // keep as illustration and for future use
910
#[inline]
1011
pub fn take_mut<T>(v: &mut T, change: impl FnOnce(T) -> T) {
1112
replace(v, |value| (change(value), ()))

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

-14
Original file line numberDiff line numberDiff line change
@@ -362,20 +362,6 @@ impl<'a, K, V> Handle<NodeRef<marker::ValMut<'a>, K, V, marker::Leaf>, marker::E
362362
}
363363
}
364364

365-
impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge> {
366-
/// Moves the leaf edge handle to the next leaf edge.
367-
///
368-
/// # Safety
369-
/// There must be another KV in the direction travelled.
370-
pub unsafe fn move_next_unchecked(&mut self) {
371-
super::mem::take_mut(self, |leaf_edge| {
372-
let kv = leaf_edge.next_kv();
373-
let kv = unsafe { unwrap_unchecked(kv.ok()) };
374-
kv.next_leaf_edge()
375-
})
376-
}
377-
}
378-
379365
impl<K, V> Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge> {
380366
/// Moves the leaf edge handle to the next leaf edge and returns the key and value
381367
/// in between, deallocating any node left behind while leaving the corresponding

0 commit comments

Comments
 (0)
Please sign in to comment.