Skip to content

Commit

Permalink
No longer favour LeafNode in NodeRef
Browse files Browse the repository at this point in the history
  • Loading branch information
ssomers committed Jan 21, 2020
1 parent 44f52ee commit 1ab4591
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 25 deletions.
8 changes: 7 additions & 1 deletion src/etc/gdb_rust_pretty_printing.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,13 +336,19 @@ def children_of_node(boxed_node, height, want_values):
head = node_ptr.dereference()
length = int(head['len'])
if length > 0:
type_name = str(node_ptr.type.target()) # alloc::...::NodeHeader<K, V, K2>
assert type_name.endswith(", ()>")
type_name = type_name[:-5] + ">"
if height > 0:
type_name = str(node_ptr.type.target()).replace('LeafNode', 'InternalNode', 1)
type_name = type_name.replace('NodeHeader', 'InternalNode', 1)
node_type = gdb.lookup_type(type_name)
node_ptr = node_ptr.cast(node_type.pointer())
leaf = node_ptr['data']
edges = node_ptr['edges']
else:
type_name = type_name.replace('NodeHeader', 'LeafNode', 1)
node_type = gdb.lookup_type(type_name)
node_ptr = node_ptr.cast(node_type.pointer())
leaf = node_ptr.dereference()
edges = None
keys = leaf['keys']
Expand Down
40 changes: 20 additions & 20 deletions src/liballoc/collections/btree/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,30 +152,34 @@ impl<K, V> InternalNode<K, V> {
}
}

/// An owned pointer to a node. This basically is either `Box<LeafNode<K, V>>` or
/// `Box<InternalNode<K, V>>`. However, it contains no information as to which of the two types
/// of nodes is actually behind the box, and, partially due to this lack of information, has no
/// destructor.
/// A managed, non-null pointer to a node. This is either an owned pointer to
/// `LeafNode<K, V>`, an owned pointer to `InternalNode<K, V>`, or a (not owned)
/// pointer to `NodeHeader<(), ()` (more specifically, the pointer to EMPTY_ROOT_NODE).
/// All of these types have a `NodeHeader<K, V>` prefix, meaning that they have at
/// least the same size as `NodeHeader<K, V>` and store the same kinds of data at the same
/// offsets; and they have a pointer alignment at least as large as `NodeHeader<K, V>`'s.
/// So that's the pointee type we store, and `as_header()` is unconditionally safe.
/// However, `BoxedNode` contains no information as to which of the three types
/// of nodes it actually contains, and, partially due to this lack of information,
/// has no destructor.
struct BoxedNode<K, V> {
ptr: Unique<LeafNode<K, V>>,
ptr: Unique<NodeHeader<K, V>>,
}

impl<K, V> BoxedNode<K, V> {
fn from_leaf(node: Box<LeafNode<K, V>>) -> Self {
BoxedNode { ptr: Box::into_unique(node) }
BoxedNode { ptr: Box::into_unique(node).cast() }
}

fn from_internal(node: Box<InternalNode<K, V>>) -> Self {
unsafe {
BoxedNode { ptr: Unique::new_unchecked(Box::into_raw(node) as *mut LeafNode<K, V>) }
}
BoxedNode { ptr: Box::into_unique(node).cast() }
}

unsafe fn from_ptr(ptr: NonNull<LeafNode<K, V>>) -> Self {
unsafe fn from_ptr(ptr: NonNull<NodeHeader<K, V>>) -> Self {
BoxedNode { ptr: Unique::from(ptr) }
}

fn as_ptr(&self) -> NonNull<LeafNode<K, V>> {
fn as_ptr(&self) -> NonNull<NodeHeader<K, V>> {
NonNull::from(self.ptr)
}
}
Expand All @@ -197,11 +201,7 @@ impl<K, V> Root<K, V> {

pub fn shared_empty_root() -> Self {
Root {
node: unsafe {
BoxedNode::from_ptr(NonNull::new_unchecked(
&EMPTY_ROOT_NODE as *const _ as *const LeafNode<K, V> as *mut _,
))
},
node: unsafe { BoxedNode::from_ptr(NonNull::from(&EMPTY_ROOT_NODE).cast()) },
height: 0,
}
}
Expand Down Expand Up @@ -310,7 +310,7 @@ impl<K, V> Root<K, V> {
/// Turning this into a `NodeHeader` reference is always safe.
pub struct NodeRef<BorrowType, K, V, Type> {
height: usize,
node: NonNull<LeafNode<K, V>>,
node: NonNull<NodeHeader<K, V>>,
// `root` is null unless the borrow type is `Mut`
root: *const Root<K, V>,
_marker: PhantomData<(BorrowType, Type)>,
Expand Down Expand Up @@ -372,11 +372,11 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
/// See `NodeRef` on why the node may not be a shared root.
unsafe fn as_leaf(&self) -> &LeafNode<K, V> {
debug_assert!(!self.is_shared_root());
self.node.as_ref()
&*(self.node.as_ptr() as *const LeafNode<K, V>)
}

fn as_header(&self) -> &NodeHeader<K, V> {
unsafe { &*(self.node.as_ptr() as *const NodeHeader<K, V>) }
unsafe { self.node.as_ref() }
}

/// Returns whether the node is the shared, empty root.
Expand Down Expand Up @@ -505,7 +505,7 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
/// This also implies you can invoke this member on the shared root, but the resulting pointer
/// might not be properly aligned and definitely would not allow accessing keys and values.
fn as_leaf_mut(&mut self) -> *mut LeafNode<K, V> {
self.node.as_ptr()
self.node.as_ptr() as *mut LeafNode<K, V>
}

/// The caller must ensure that the node is not the shared root.
Expand Down
8 changes: 4 additions & 4 deletions src/test/debuginfo/pretty-std-collections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
// gdb-check:$3 = BTreeMap<(), ()>(len: 0)

// gdb-command: print nasty_btree_map
// gdb-check:$4 = BTreeMap<i32, pretty_std_collections::MyLeafNode>(len: 1) = {[1] = pretty_std_collections::MyLeafNode (11)}
// gdb-check:$4 = BTreeMap<i32, pretty_std_collections::MyNodeHeader>(len: 1) = {[1] = pretty_std_collections::MyNodeHeader (11)}

// gdb-command: print vec_deque
// gdb-check:$5 = VecDeque<i32>(len: 3, cap: 8) = {5, 3, 7}
Expand All @@ -37,7 +37,7 @@ use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::collections::VecDeque;

struct MyLeafNode(i32); // helps to ensure we don't blindly replace substring "LeafNode"
struct MyNodeHeader(i32); // helps to ensure we don't blindly replace substring "NodeHeader"

fn main() {
// BTreeSet
Expand All @@ -52,8 +52,8 @@ fn main() {
btree_map.insert(i, i);
}
let empty_btree_map: BTreeMap<(), ()> = BTreeMap::new();
let mut nasty_btree_map: BTreeMap<i32, MyLeafNode> = BTreeMap::new();
nasty_btree_map.insert(1, MyLeafNode(11));
let mut nasty_btree_map: BTreeMap<i32, MyNodeHeader> = BTreeMap::new();
nasty_btree_map.insert(1, MyNodeHeader(11));

// VecDeque
let mut vec_deque = VecDeque::new();
Expand Down

0 comments on commit 1ab4591

Please sign in to comment.