Skip to content

Commit 1ab4591

Browse files
committed
No longer favour LeafNode in NodeRef
1 parent 44f52ee commit 1ab4591

File tree

3 files changed

+31
-25
lines changed

3 files changed

+31
-25
lines changed

src/etc/gdb_rust_pretty_printing.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,13 +336,19 @@ def children_of_node(boxed_node, height, want_values):
336336
head = node_ptr.dereference()
337337
length = int(head['len'])
338338
if length > 0:
339+
type_name = str(node_ptr.type.target()) # alloc::...::NodeHeader<K, V, K2>
340+
assert type_name.endswith(", ()>")
341+
type_name = type_name[:-5] + ">"
339342
if height > 0:
340-
type_name = str(node_ptr.type.target()).replace('LeafNode', 'InternalNode', 1)
343+
type_name = type_name.replace('NodeHeader', 'InternalNode', 1)
341344
node_type = gdb.lookup_type(type_name)
342345
node_ptr = node_ptr.cast(node_type.pointer())
343346
leaf = node_ptr['data']
344347
edges = node_ptr['edges']
345348
else:
349+
type_name = type_name.replace('NodeHeader', 'LeafNode', 1)
350+
node_type = gdb.lookup_type(type_name)
351+
node_ptr = node_ptr.cast(node_type.pointer())
346352
leaf = node_ptr.dereference()
347353
edges = None
348354
keys = leaf['keys']

src/liballoc/collections/btree/node.rs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -152,30 +152,34 @@ impl<K, V> InternalNode<K, V> {
152152
}
153153
}
154154

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

163169
impl<K, V> BoxedNode<K, V> {
164170
fn from_leaf(node: Box<LeafNode<K, V>>) -> Self {
165-
BoxedNode { ptr: Box::into_unique(node) }
171+
BoxedNode { ptr: Box::into_unique(node).cast() }
166172
}
167173

168174
fn from_internal(node: Box<InternalNode<K, V>>) -> Self {
169-
unsafe {
170-
BoxedNode { ptr: Unique::new_unchecked(Box::into_raw(node) as *mut LeafNode<K, V>) }
171-
}
175+
BoxedNode { ptr: Box::into_unique(node).cast() }
172176
}
173177

174-
unsafe fn from_ptr(ptr: NonNull<LeafNode<K, V>>) -> Self {
178+
unsafe fn from_ptr(ptr: NonNull<NodeHeader<K, V>>) -> Self {
175179
BoxedNode { ptr: Unique::from(ptr) }
176180
}
177181

178-
fn as_ptr(&self) -> NonNull<LeafNode<K, V>> {
182+
fn as_ptr(&self) -> NonNull<NodeHeader<K, V>> {
179183
NonNull::from(self.ptr)
180184
}
181185
}
@@ -197,11 +201,7 @@ impl<K, V> Root<K, V> {
197201

198202
pub fn shared_empty_root() -> Self {
199203
Root {
200-
node: unsafe {
201-
BoxedNode::from_ptr(NonNull::new_unchecked(
202-
&EMPTY_ROOT_NODE as *const _ as *const LeafNode<K, V> as *mut _,
203-
))
204-
},
204+
node: unsafe { BoxedNode::from_ptr(NonNull::from(&EMPTY_ROOT_NODE).cast()) },
205205
height: 0,
206206
}
207207
}
@@ -310,7 +310,7 @@ impl<K, V> Root<K, V> {
310310
/// Turning this into a `NodeHeader` reference is always safe.
311311
pub struct NodeRef<BorrowType, K, V, Type> {
312312
height: usize,
313-
node: NonNull<LeafNode<K, V>>,
313+
node: NonNull<NodeHeader<K, V>>,
314314
// `root` is null unless the borrow type is `Mut`
315315
root: *const Root<K, V>,
316316
_marker: PhantomData<(BorrowType, Type)>,
@@ -372,11 +372,11 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
372372
/// See `NodeRef` on why the node may not be a shared root.
373373
unsafe fn as_leaf(&self) -> &LeafNode<K, V> {
374374
debug_assert!(!self.is_shared_root());
375-
self.node.as_ref()
375+
&*(self.node.as_ptr() as *const LeafNode<K, V>)
376376
}
377377

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

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

511511
/// The caller must ensure that the node is not the shared root.

src/test/debuginfo/pretty-std-collections.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
// gdb-check:$3 = BTreeMap<(), ()>(len: 0)
2525

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

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

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

4242
fn main() {
4343
// BTreeSet
@@ -52,8 +52,8 @@ fn main() {
5252
btree_map.insert(i, i);
5353
}
5454
let empty_btree_map: BTreeMap<(), ()> = BTreeMap::new();
55-
let mut nasty_btree_map: BTreeMap<i32, MyLeafNode> = BTreeMap::new();
56-
nasty_btree_map.insert(1, MyLeafNode(11));
55+
let mut nasty_btree_map: BTreeMap<i32, MyNodeHeader> = BTreeMap::new();
56+
nasty_btree_map.insert(1, MyNodeHeader(11));
5757

5858
// VecDeque
5959
let mut vec_deque = VecDeque::new();

0 commit comments

Comments
 (0)