Skip to content

Commit 7889373

Browse files
RalfJungMark-Simulacrum
authored andcommitted
make as_leaf return a raw pointer, to reduce aliasing assumptions
1 parent f76eda3 commit 7889373

File tree

1 file changed

+12
-7
lines changed
  • library/alloc/src/collections/btree

1 file changed

+12
-7
lines changed

library/alloc/src/collections/btree/node.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,9 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
316316
/// Note that, despite being safe, calling this function can have the side effect
317317
/// of invalidating mutable references that unsafe code has created.
318318
pub fn len(&self) -> usize {
319-
self.as_leaf().len as usize
319+
// Crucially, we only access the `len` field here. There might be outstanding mutable references
320+
// to keys/values that we must not invalidate.
321+
unsafe { (*self.as_leaf()).len as usize }
320322
}
321323

322324
/// Returns the height of this node in the whole tree. Zero height denotes the
@@ -334,11 +336,14 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
334336
/// If the node is a leaf, this function simply opens up its data.
335337
/// If the node is an internal node, so not a leaf, it does have all the data a leaf has
336338
/// (header, keys and values), and this function exposes that.
337-
fn as_leaf(&self) -> &LeafNode<K, V> {
339+
///
340+
/// Returns a raw ptr to avoid invalidating other references to this node
341+
/// (such as during iteration).
342+
fn as_leaf(&self) -> *const LeafNode<K, V> {
338343
// The node must be valid for at least the LeafNode portion.
339344
// This is not a reference in the NodeRef type because we don't know if
340345
// it should be unique or shared.
341-
unsafe { self.node.as_ref() }
346+
self.node.as_ptr()
342347
}
343348

344349
/// Borrows a view into the keys stored in the node.
@@ -361,7 +366,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
361366
pub fn ascend(
362367
self,
363368
) -> Result<Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::Edge>, Self> {
364-
let parent_as_leaf = self.as_leaf().parent as *const LeafNode<K, V>;
369+
let parent_as_leaf = unsafe { (*self.as_leaf()).parent as *const LeafNode<K, V> };
365370
if let Some(non_zero) = NonNull::new(parent_as_leaf as *mut _) {
366371
Ok(Handle {
367372
node: NodeRef {
@@ -370,7 +375,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
370375
root: self.root,
371376
_marker: PhantomData,
372377
},
373-
idx: unsafe { usize::from(*self.as_leaf().parent_idx.as_ptr()) },
378+
idx: unsafe { usize::from(*(*self.as_leaf()).parent_idx.as_ptr()) },
374379
_marker: PhantomData,
375380
})
376381
} else {
@@ -475,13 +480,13 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
475480
impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
476481
fn into_key_slice(self) -> &'a [K] {
477482
unsafe {
478-
slice::from_raw_parts(MaybeUninit::slice_as_ptr(&self.as_leaf().keys), self.len())
483+
slice::from_raw_parts(MaybeUninit::slice_as_ptr(&(*self.as_leaf()).keys), self.len())
479484
}
480485
}
481486

482487
fn into_val_slice(self) -> &'a [V] {
483488
unsafe {
484-
slice::from_raw_parts(MaybeUninit::slice_as_ptr(&self.as_leaf().vals), self.len())
489+
slice::from_raw_parts(MaybeUninit::slice_as_ptr(&(*self.as_leaf()).vals), self.len())
485490
}
486491
}
487492
}

0 commit comments

Comments
 (0)