Rollup merge of #147814 - hkBst:btree-4, r=joboet

btree: some cleanup with less unsafe
This commit is contained in:
Matthias Krüger
2025-10-20 18:21:34 +02:00
committed by GitHub

View File

@@ -33,6 +33,7 @@
use core::marker::PhantomData; use core::marker::PhantomData;
use core::mem::{self, MaybeUninit}; use core::mem::{self, MaybeUninit};
use core::num::NonZero;
use core::ptr::{self, NonNull}; use core::ptr::{self, NonNull};
use core::slice::SliceIndex; use core::slice::SliceIndex;
@@ -143,7 +144,7 @@ type BoxedNode<K, V> = NonNull<LeafNode<K, V>>;
/// ///
/// A reference to a node. /// A reference to a node.
/// ///
/// This type has a number of parameters that controls how it acts: /// This type has a number of parameters that control how it acts:
/// - `BorrowType`: A dummy type that describes the kind of borrow and carries a lifetime. /// - `BorrowType`: A dummy type that describes the kind of borrow and carries a lifetime.
/// - When this is `Immut<'a>`, the `NodeRef` acts roughly like `&'a Node`. /// - When this is `Immut<'a>`, the `NodeRef` acts roughly like `&'a Node`.
/// - When this is `ValMut<'a>`, the `NodeRef` acts roughly like `&'a Node` /// - When this is `ValMut<'a>`, the `NodeRef` acts roughly like `&'a Node`
@@ -226,33 +227,27 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::Leaf> {
fn from_new_leaf<A: Allocator + Clone>(leaf: Box<LeafNode<K, V>, A>) -> Self { fn from_new_leaf<A: Allocator + Clone>(leaf: Box<LeafNode<K, V>, A>) -> Self {
// The allocator must be dropped, not leaked. See also `BTreeMap::alloc`. // The allocator must be dropped, not leaked. See also `BTreeMap::alloc`.
let (leaf, _alloc) = Box::into_raw_with_allocator(leaf); let (node, _alloc) = Box::into_non_null_with_allocator(leaf);
// SAFETY: the node was just allocated.
let node = unsafe { NonNull::new_unchecked(leaf) };
NodeRef { height: 0, node, _marker: PhantomData } NodeRef { height: 0, node, _marker: PhantomData }
} }
} }
impl<K, V> NodeRef<marker::Owned, K, V, marker::Internal> { impl<K, V> NodeRef<marker::Owned, K, V, marker::Internal> {
/// Creates a new internal (height > 0) `NodeRef`
fn new_internal<A: Allocator + Clone>(child: Root<K, V>, alloc: A) -> Self { fn new_internal<A: Allocator + Clone>(child: Root<K, V>, alloc: A) -> Self {
let mut new_node = unsafe { InternalNode::new(alloc) }; let mut new_node = unsafe { InternalNode::new(alloc) };
new_node.edges[0].write(child.node); new_node.edges[0].write(child.node);
unsafe { NodeRef::from_new_internal(new_node, child.height + 1) } NodeRef::from_new_internal(new_node, NonZero::new(child.height + 1).unwrap())
} }
/// # Safety /// Creates a new internal (height > 0) `NodeRef` from an existing internal node
/// `height` must not be zero. fn from_new_internal<A: Allocator + Clone>(
unsafe fn from_new_internal<A: Allocator + Clone>(
internal: Box<InternalNode<K, V>, A>, internal: Box<InternalNode<K, V>, A>,
height: usize, height: NonZero<usize>,
) -> Self { ) -> Self {
debug_assert!(height > 0);
// The allocator must be dropped, not leaked. See also `BTreeMap::alloc`. // The allocator must be dropped, not leaked. See also `BTreeMap::alloc`.
let (internal, _alloc) = Box::into_raw_with_allocator(internal); let (node, _alloc) = Box::into_non_null_with_allocator(internal);
// SAFETY: the node was just allocated. let mut this = NodeRef { height: height.into(), node: node.cast(), _marker: PhantomData };
let internal = unsafe { NonNull::new_unchecked(internal) };
let node = internal.cast();
let mut this = NodeRef { height, node, _marker: PhantomData };
this.borrow_mut().correct_all_childrens_parent_links(); this.borrow_mut().correct_all_childrens_parent_links();
this this
} }
@@ -625,9 +620,8 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
let top = self.node; let top = self.node;
// SAFETY: we asserted to be internal. // SAFETY: we asserted to be internal.
let internal_self = unsafe { self.borrow_mut().cast_to_internal_unchecked() }; let mut internal_self = unsafe { self.borrow_mut().cast_to_internal_unchecked() };
// SAFETY: we borrowed `self` exclusively and its borrow type is exclusive. let internal_node = internal_self.as_internal_mut();
let internal_node = unsafe { &mut *NodeRef::as_internal_ptr(&internal_self) };
// SAFETY: the first edge is always initialized. // SAFETY: the first edge is always initialized.
self.node = unsafe { internal_node.edges[0].assume_init_read() }; self.node = unsafe { internal_node.edges[0].assume_init_read() };
self.height -= 1; self.height -= 1;
@@ -1305,7 +1299,8 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>,
&mut new_node.edges[..new_len + 1], &mut new_node.edges[..new_len + 1],
); );
let height = self.node.height; // SAFETY: self is `marker::Internal`, so `self.node.height` is positive
let height = NonZero::new_unchecked(self.node.height);
let right = NodeRef::from_new_internal(new_node, height); let right = NodeRef::from_new_internal(new_node, height);
SplitResult { left: self.node, kv, right } SplitResult { left: self.node, kv, right }