diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index e3e555a72de02..5cc5aebc3afdc 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -33,7 +33,6 @@ use core::marker::PhantomData; use core::mem::{self, MaybeUninit}; use core::ptr::{self, NonNull}; -use crate::alloc::{AllocRef, Global, Layout}; use crate::boxed::Box; const B: usize = 6; @@ -107,27 +106,96 @@ impl InternalNode { } } -/// A managed, non-null pointer to a node. This is either an owned pointer to -/// `LeafNode` or an owned pointer to `InternalNode`. -/// -/// However, `BoxedNode` contains no information as to which of the two types -/// of nodes it actually contains, and, partially due to this lack of information, -/// has no destructor. -struct BoxedNode { - ptr: NonNull>, -} +use ptr_fortress::*; +mod ptr_fortress { + use super::{Box, InternalNode, LeafNode, NonNull}; + use crate::alloc::{AllocRef, Global, Layout}; -impl BoxedNode { - fn from_owned(ptr: NonNull>) -> Self { - BoxedNode { ptr } + /// A managed, non-null pointer to a node. This is either an owned pointer to + /// `LeafNode` or an owned pointer to `InternalNode`. + /// + /// However, `BoxedNode` contains no information as to which of the two types + /// of nodes it actually contains, and, partially due to this lack of information, + /// has no destructor. + pub(super) struct BoxedNode { + ptr: NonNull>, } - fn as_ptr(&self) -> NonNull> { - self.ptr + /// A managed, non-null pointer to a node. This is either owned or shared, + /// and points to either a `LeafNode` or an `InternalNode`. + /// + /// However, `NodePtr` contains no information as to whether it owns or + /// shares, and which of the two types of nodes it actually points to. + /// + /// It wraps and acts like a raw pointer to avoid invalidating other + /// references to the same node. + pub(super) struct NodePtr { + ptr: NonNull>, + } + + impl NodePtr { + pub(super) fn from_new_leaf(leaf: Box>) -> Self { + NodePtr { ptr: NonNull::from(Box::leak(leaf)) } + } + + pub(super) fn from_new_internal(internal: Box>) -> Self { + NodePtr { ptr: NonNull::from(Box::leak(internal)).cast() } + } + + /// Create from a parent pointer stored in LeafNode. + pub(super) fn from_internal(internal_ptr: NonNull>) -> Self { + NodePtr { ptr: internal_ptr.cast() } + } + + pub(super) fn from_boxed_node(boxed_node: BoxedNode) -> Self { + NodePtr { ptr: NonNull::from(boxed_node.ptr) } + } + + pub(super) fn into_boxed_node(self) -> BoxedNode { + BoxedNode { ptr: self.ptr } + } + + /// Implementation of PartialEq, but there's no need to announce that trait. + pub(super) fn eq(&self, other: &Self) -> bool { + let Self { ptr } = self; + *ptr == other.ptr + } + + /// Exposes the leaf portion of any leaf or internal node. + pub(super) fn as_leaf_ptr(this: &Self) -> *mut LeafNode { + this.ptr.as_ptr() + } + + /// Exposes an internal node. + /// # Safety + /// The node must not be a leaf. + pub(super) unsafe fn as_internal_ptr(this: &Self) -> *mut InternalNode { + this.ptr.as_ptr() as *mut _ + } + + /// # Safety + /// The node must be a leaf. + pub(super) unsafe fn dealloc_leaf(self) { + unsafe { Global.dealloc(self.ptr.cast(), Layout::new::>()) } + } + + /// # Safety + /// The node must not be a leaf. + pub(super) unsafe fn dealloc_internal(self) { + unsafe { Global.dealloc(self.ptr.cast(), Layout::new::>()) } + } + } + + impl Copy for NodePtr {} + impl Clone for NodePtr { + fn clone(&self) -> Self { + *self + } } } -/// An owned tree. +/// An owned tree. Also, the volatile representation of the contents of an internal edge, +/// at times when those contents are not packed into a BoxedNode. /// /// Note that this does not have a destructor, and must be cleaned up manually. pub type Root = NodeRef; @@ -145,13 +213,13 @@ impl NodeRef { } fn from_new_leaf(leaf: Box>) -> Self { - NodeRef { height: 0, node: NonNull::from(Box::leak(leaf)), _marker: PhantomData } + NodeRef { height: 0, node: NodePtr::from_new_leaf(leaf), _marker: PhantomData } } } impl NodeRef { fn from_new_internal(internal: Box>, height: usize) -> Self { - NodeRef { height, node: NonNull::from(Box::leak(internal)).cast(), _marker: PhantomData } + NodeRef { height, node: NodePtr::from_new_internal(internal), _marker: PhantomData } } } @@ -171,7 +239,7 @@ impl NodeRef { /// Packs the reference, aware of type and height, into a type-agnostic pointer. fn into_boxed_node(self) -> BoxedNode { - BoxedNode::from_owned(self.node) + self.node.into_boxed_node() } } @@ -181,7 +249,7 @@ impl NodeRef { /// and is the opposite of `pop_internal_level`. pub fn push_internal_level(&mut self) -> NodeRef, K, V, marker::Internal> { let mut new_node = Box::new(unsafe { InternalNode::new() }); - new_node.edges[0].write(BoxedNode::from_owned(self.node)); + new_node.edges[0].write(self.node.into_boxed_node()); let mut new_root = NodeRef::from_new_internal(new_node, self.height + 1); new_root.borrow_mut().first_edge().correct_parent_link(); *self = new_root.forget_type(); @@ -209,7 +277,7 @@ impl NodeRef { self.borrow_mut().clear_parent_link(); unsafe { - Global.dealloc(top.cast(), Layout::new::>()); + top.dealloc_internal(); } } } @@ -270,7 +338,7 @@ pub struct NodeRef { height: usize, /// The pointer to the leaf or internal node. The definition of `InternalNode` /// ensures that the pointer is valid either way. - node: NonNull>, + node: NodePtr, _marker: PhantomData<(BorrowType, Type)>, } @@ -291,7 +359,7 @@ unsafe impl Send for NodeRef impl NodeRef { /// Unpack a node reference that was packed by `Root::into_boxed_node`. fn from_boxed_node(boxed_node: BoxedNode, height: usize) -> Self { - NodeRef { height, node: boxed_node.as_ptr(), _marker: PhantomData } + NodeRef { height, node: NodePtr::from_boxed_node(boxed_node), _marker: PhantomData } } } @@ -299,7 +367,7 @@ impl NodeRef { /// Unpack a node reference that was packed as `NodeRef::parent`. fn from_internal(node: NonNull>, height: usize) -> Self { debug_assert!(height > 0); - NodeRef { height, node: node.cast(), _marker: PhantomData } + NodeRef { height, node: NodePtr::from_internal(node), _marker: PhantomData } } } @@ -309,7 +377,7 @@ impl NodeRef { /// Returns a raw ptr to avoid invalidating other references to this node. fn as_internal_ptr(this: &Self) -> *mut InternalNode { // SAFETY: the static node type is `Internal`. - this.node.as_ptr() as *mut InternalNode + unsafe { NodePtr::as_internal_ptr(&this.node) } } } @@ -359,7 +427,7 @@ impl NodeRef { // The node must be valid for at least the LeafNode portion. // This is not a reference in the NodeRef type because we don't know if // it should be unique or shared. - this.node.as_ptr() + NodePtr::as_leaf_ptr(&this.node) } } @@ -461,15 +529,10 @@ impl NodeRef { let height = self.height; let node = self.node; let ret = self.ascend().ok(); - unsafe { - Global.dealloc( - node.cast(), - if height > 0 { - Layout::new::>() - } else { - Layout::new::>() - }, - ); + if height > 0 { + unsafe { node.dealloc_internal() }; + } else { + unsafe { node.dealloc_leaf() }; } ret } @@ -1421,9 +1484,9 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { left_node.correct_childrens_parent_links(left_len + 1..=left_len + 1 + right_len); - Global.dealloc(right_node.node.cast(), Layout::new::>()); + right_node.node.dealloc_internal(); } else { - Global.dealloc(right_node.node.cast(), Layout::new::>()); + right_node.node.dealloc_leaf(); } let new_idx = match track_edge_idx { diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py index b5ade324bba10..b98682b2e1109 100644 --- a/src/etc/gdb_providers.py +++ b/src/etc/gdb_providers.py @@ -239,7 +239,8 @@ def cast_to_internal(node): if root.type.name.startswith("core::option::Option<"): root = root.cast(gdb.lookup_type(root.type.name[21:-1])) node_ptr = root["node"] - if node_ptr.type.name.startswith("alloc::collections::btree::node::BoxedNode<"): + if node_ptr.type.name.startswith("alloc::collections::btree::node::BoxedNode<") \ + or node_ptr.type.name.startswith("alloc::collections::btree::node::ptr_fortress::NodePtr<"): node_ptr = node_ptr["ptr"] node_ptr = unwrap_unique_or_non_null(node_ptr) height = root["height"]