Skip to content

Commit 417eefe

Browse files
committed
BTreeMap: stop tree from being owned by non-root node
1 parent 7907345 commit 417eefe

File tree

5 files changed

+73
-32
lines changed

5 files changed

+73
-32
lines changed

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,8 @@ pub struct IterMut<'a, K: 'a, V: 'a> {
300300
/// [`into_iter`]: IntoIterator::into_iter
301301
#[stable(feature = "rust1", since = "1.0.0")]
302302
pub struct IntoIter<K, V> {
303-
front: Option<Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>>,
304-
back: Option<Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>>,
303+
front: Option<Handle<NodeRef<marker::Dying, K, V, marker::Leaf>, marker::Edge>>,
304+
back: Option<Handle<NodeRef<marker::Dying, K, V, marker::Leaf>, marker::Edge>>,
305305
length: usize,
306306
}
307307

@@ -1364,7 +1364,7 @@ impl<K, V> IntoIterator for BTreeMap<K, V> {
13641364
fn into_iter(self) -> IntoIter<K, V> {
13651365
let mut me = ManuallyDrop::new(self);
13661366
if let Some(root) = me.root.take() {
1367-
let (f, b) = root.full_range();
1367+
let (f, b) = root.into_dying().full_range();
13681368

13691369
IntoIter { front: Some(f), back: Some(b), length: me.length }
13701370
} else {

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

+18-12
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use super::unwrap_unchecked;
1212
///
1313
/// The result is meaningful only if the tree is ordered by key, like the tree
1414
/// in a `BTreeMap` is.
15-
fn range_search<BorrowType, K, V, Q, R>(
15+
fn range_search<BorrowType: marker::BorrowType, K, V, Q, R>(
1616
root1: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
1717
root2: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
1818
range: R,
@@ -105,7 +105,7 @@ where
105105
}
106106

107107
/// Equivalent to `range_search(k, v, ..)` but without the `Ord` bound.
108-
fn full_range<BorrowType, K, V>(
108+
fn full_range<BorrowType: marker::BorrowType, K, V>(
109109
root1: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
110110
root2: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
111111
) -> (
@@ -202,15 +202,15 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::ValMut<'a>, K, V, marker::LeafOrInternal>
202202
}
203203
}
204204

205-
impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
205+
impl<K, V> NodeRef<marker::Dying, K, V, marker::LeafOrInternal> {
206206
/// Splits a unique reference into a pair of leaf edges delimiting the full range of the tree.
207207
/// The results are non-unique references allowing massively destructive mutation, so must be
208208
/// used with the utmost care.
209209
pub fn full_range(
210210
self,
211211
) -> (
212-
Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>,
213-
Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>,
212+
Handle<NodeRef<marker::Dying, K, V, marker::Leaf>, marker::Edge>,
213+
Handle<NodeRef<marker::Dying, K, V, marker::Leaf>, marker::Edge>,
214214
) {
215215
// We duplicate the root NodeRef here -- we will never access it in a way
216216
// that overlaps references obtained from the root.
@@ -219,7 +219,9 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
219219
}
220220
}
221221

222-
impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
222+
impl<BorrowType: marker::BorrowType, K, V>
223+
Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>
224+
{
223225
/// Given a leaf edge handle, returns [`Result::Ok`] with a handle to the neighboring KV
224226
/// on the right side, which is either in the same leaf node or in an ancestor node.
225227
/// If the leaf edge is the last one in the tree, returns [`Result::Err`] with the root node.
@@ -263,7 +265,9 @@ impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::E
263265
}
264266
}
265267

266-
impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::Edge> {
268+
impl<BorrowType: marker::BorrowType, K, V>
269+
Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::Edge>
270+
{
267271
/// Given an internal edge handle, returns [`Result::Ok`] with a handle to the neighboring KV
268272
/// on the right side, which is either in the same internal node or in an ancestor node.
269273
/// If the internal edge is the last one in the tree, returns [`Result::Err`] with the root node.
@@ -297,8 +301,8 @@ macro_rules! def_next_kv_uncheched_dealloc {
297301
/// - The node carrying the next KV returned must not have been deallocated by a
298302
/// previous call on any handle obtained for this tree.
299303
unsafe fn $name <K, V>(
300-
leaf_edge: Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>,
301-
) -> Handle<NodeRef<marker::Owned, K, V, marker::LeafOrInternal>, marker::KV> {
304+
leaf_edge: Handle<NodeRef<marker::Dying, K, V, marker::Leaf>, marker::Edge>,
305+
) -> Handle<NodeRef<marker::Dying, K, V, marker::LeafOrInternal>, marker::KV> {
302306
let mut edge = leaf_edge.forget_node_type();
303307
loop {
304308
edge = match edge.$adjacent_kv() {
@@ -378,7 +382,7 @@ impl<'a, K, V> Handle<NodeRef<marker::ValMut<'a>, K, V, marker::Leaf>, marker::E
378382
}
379383
}
380384

381-
impl<K, V> Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge> {
385+
impl<K, V> Handle<NodeRef<marker::Dying, K, V, marker::Leaf>, marker::Edge> {
382386
/// Moves the leaf edge handle to the next leaf edge and returns the key and value
383387
/// in between, deallocating any node left behind while leaving the corresponding
384388
/// edge in its parent node dangling.
@@ -422,7 +426,7 @@ impl<K, V> Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge> {
422426
}
423427
}
424428

425-
impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
429+
impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
426430
/// Returns the leftmost leaf edge in or underneath a node - in other words, the edge
427431
/// you need first when navigating forward (or last when navigating backward).
428432
#[inline]
@@ -503,7 +507,9 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>
503507
}
504508
}
505509

506-
impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, marker::KV> {
510+
impl<BorrowType: marker::BorrowType, K, V>
511+
Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, marker::KV>
512+
{
507513
/// Returns the leaf edge closest to a KV for forward navigation.
508514
pub fn next_leaf_edge(self) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
509515
match self.force() {

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

+49-14
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ struct InternalNode<K, V> {
9393
data: LeafNode<K, V>,
9494

9595
/// The pointers to the children of this node. `len + 1` of these are considered
96-
/// initialized and valid. Although during the process of `into_iter` or `drop`,
97-
/// some pointers are dangling while others still need to be traversed.
96+
/// initialized and valid, except that near the end, while the tree is held
97+
/// through borrow type `Dying`, some of these pointers are dangling.
9898
edges: [MaybeUninit<BoxedNode<K, V>>; 2 * B],
9999
}
100100

@@ -119,7 +119,7 @@ impl<K, V> InternalNode<K, V> {
119119
/// is not a separate type and has no destructor.
120120
type BoxedNode<K, V> = NonNull<LeafNode<K, V>>;
121121

122-
/// An owned tree.
122+
/// The root node of an owned tree.
123123
///
124124
/// Note that this does not have a destructor, and must be cleaned up manually.
125125
pub type Root<K, V> = NodeRef<marker::Owned, K, V, marker::LeafOrInternal>;
@@ -157,18 +157,23 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::Internal> {
157157
}
158158

159159
impl<K, V, Type> NodeRef<marker::Owned, K, V, Type> {
160-
/// Mutably borrows the owned node. Unlike `reborrow_mut`, this is safe,
161-
/// because the return value cannot be used to destroy the node itself,
162-
/// and there cannot be other references to the tree (except during the
163-
/// process of `into_iter` or `drop`, but that is horrific already).
160+
/// Mutably borrows the owned root node. Unlike `reborrow_mut`, this is safe
161+
/// because the return value cannot be used to destroy the root, and there
162+
/// cannot be other references to the tree.
164163
pub fn borrow_mut(&mut self) -> NodeRef<marker::Mut<'_>, K, V, Type> {
165164
NodeRef { height: self.height, node: self.node, _marker: PhantomData }
166165
}
167166

168-
/// Slightly mutably borrows the owned node.
167+
/// Slightly mutably borrows the owned root node.
169168
pub fn borrow_valmut(&mut self) -> NodeRef<marker::ValMut<'_>, K, V, Type> {
170169
NodeRef { height: self.height, node: self.node, _marker: PhantomData }
171170
}
171+
172+
/// Irreversibly transistions to a reference that offers traversal,
173+
/// destructive methods and little else.
174+
pub fn into_dying(self) -> NodeRef<marker::Dying, K, V, Type> {
175+
NodeRef { height: self.height, node: self.node, _marker: PhantomData }
176+
}
172177
}
173178

174179
impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
@@ -196,8 +201,13 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
196201

197202
let top = self.node;
198203

199-
let internal_node = NodeRef { height: self.height, node: top, _marker: PhantomData };
200-
*self = internal_node.first_edge().descend();
204+
// SAFETY: we asserted to be internal.
205+
let internal_self = unsafe { self.borrow_mut().cast_to_internal_unchecked() };
206+
// SAFETY: we borrowed `self` exclusively and its borrow type is exclusive.
207+
let internal_node = unsafe { &mut *NodeRef::as_internal_ptr(&internal_self) };
208+
// SAFETY: the first edge is always initialized.
209+
self.node = unsafe { internal_node.edges[0].assume_init_read() };
210+
self.height -= 1;
201211
self.clear_parent_link();
202212

203213
unsafe {
@@ -224,6 +234,9 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
224234
/// although insert methods allow a mutable pointer to a value to coexist.
225235
/// - When this is `Owned`, the `NodeRef` acts roughly like `Box<Node>`,
226236
/// but does not have a destructor, and must be cleaned up manually.
237+
/// - When this is `Dying`, the `NodeRef` still acts roughly like `Box<Node>`,
238+
/// but has methods to destroy the tree bit by bit, and ordinary methods,
239+
/// while not marked as unsafe to call, can invoke UB if called incorrectly.
227240
/// Since any `NodeRef` allows navigating through the tree, `BorrowType`
228241
/// effectively applies to the entire tree, not just to the node itself.
229242
/// - `K` and `V`: These are the types of keys and values stored in the nodes.
@@ -280,6 +293,7 @@ unsafe impl<'a, K: Sync + 'a, V: Sync + 'a, Type> Send for NodeRef<marker::Immut
280293
unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef<marker::Mut<'a>, K, V, Type> {}
281294
unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef<marker::ValMut<'a>, K, V, Type> {}
282295
unsafe impl<K: Send, V: Send, Type> Send for NodeRef<marker::Owned, K, V, Type> {}
296+
unsafe impl<K: Send, V: Send, Type> Send for NodeRef<marker::Dying, K, V, Type> {}
283297

284298
impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Internal> {
285299
/// Unpack a node reference that was packed as `NodeRef::parent`.
@@ -343,7 +357,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
343357
}
344358
}
345359

346-
impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
360+
impl<BorrowType: marker::BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
347361
/// Finds the parent of the current node. Returns `Ok(handle)` if the current
348362
/// node actually has a parent, where `handle` points to the edge of the parent
349363
/// that points to the current node. Returns `Err(self)` if the current node has
@@ -356,6 +370,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
356370
pub fn ascend(
357371
self,
358372
) -> Result<Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::Edge>, Self> {
373+
assert!(BorrowType::PERMITS_TRAVERSAL);
359374
// We need to use raw pointers to nodes because, if BorrowType is marker::ValMut,
360375
// there might be outstanding mutable references to values that we must not invalidate.
361376
let leaf_ptr: *const _ = Self::as_leaf_ptr(&self);
@@ -410,13 +425,13 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
410425
}
411426
}
412427

413-
impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
428+
impl<K, V> NodeRef<marker::Dying, K, V, marker::LeafOrInternal> {
414429
/// Similar to `ascend`, gets a reference to a node's parent node, but also
415430
/// deallocates the current node in the process. This is unsafe because the
416431
/// current node will still be accessible despite being deallocated.
417432
pub unsafe fn deallocate_and_ascend(
418433
self,
419-
) -> Option<Handle<NodeRef<marker::Owned, K, V, marker::Internal>, marker::Edge>> {
434+
) -> Option<Handle<NodeRef<marker::Dying, K, V, marker::Internal>, marker::Edge>> {
420435
let height = self.height;
421436
let node = self.node;
422437
let ret = self.ascend().ok();
@@ -951,14 +966,17 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
951966
}
952967
}
953968

954-
impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::Edge> {
969+
impl<BorrowType: marker::BorrowType, K, V>
970+
Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::Edge>
971+
{
955972
/// Finds the node pointed to by this edge.
956973
///
957974
/// The method name assumes you picture trees with the root node on top.
958975
///
959976
/// `edge.descend().ascend().unwrap()` and `node.ascend().unwrap().descend()` should
960977
/// both, upon success, do nothing.
961978
pub fn descend(self) -> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
979+
assert!(BorrowType::PERMITS_TRAVERSAL);
962980
// We need to use raw pointers to nodes because, if BorrowType is
963981
// marker::ValMut, there might be outstanding mutable references to
964982
// values that we must not invalidate. There's no worry accessing the
@@ -1596,10 +1614,27 @@ pub mod marker {
15961614
pub enum LeafOrInternal {}
15971615

15981616
pub enum Owned {}
1617+
pub enum Dying {}
15991618
pub struct Immut<'a>(PhantomData<&'a ()>);
16001619
pub struct Mut<'a>(PhantomData<&'a mut ()>);
16011620
pub struct ValMut<'a>(PhantomData<&'a mut ()>);
16021621

1622+
pub trait BorrowType {
1623+
// Whether node references of this borrow type allow traversing
1624+
// to other nodes in the tree.
1625+
const PERMITS_TRAVERSAL: bool = true;
1626+
}
1627+
impl BorrowType for Owned {
1628+
// Traversal isn't needede, it happens using the result of `borrow_mut`.
1629+
// By disabling traversal, and only creating new references to roots,
1630+
// we know that every reference of the `Owned` type is to a root node.
1631+
const PERMITS_TRAVERSAL: bool = false;
1632+
}
1633+
impl BorrowType for Dying {}
1634+
impl<'a> BorrowType for Immut<'a> {}
1635+
impl<'a> BorrowType for Mut<'a> {}
1636+
impl<'a> BorrowType for ValMut<'a> {}
1637+
16031638
pub enum KV {}
16041639
pub enum Edge {}
16051640
}

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ fn test_partial_cmp_eq() {
9595
assert_eq!(top_edge_1.partial_cmp(&top_edge_2), None);
9696

9797
root1.pop_internal_level();
98-
unsafe { root1.deallocate_and_ascend() };
99-
unsafe { root2.deallocate_and_ascend() };
98+
unsafe { root1.into_dying().deallocate_and_ascend() };
99+
unsafe { root2.into_dying().deallocate_and_ascend() };
100100
}
101101

102102
#[test]

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub enum IndexResult {
1515
Edge(usize),
1616
}
1717

18-
impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
18+
impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
1919
/// Looks up a given key in a (sub)tree headed by the node, recursively.
2020
/// Returns a `Found` with the handle of the matching KV, if any. Otherwise,
2121
/// returns a `GoDown` with the handle of the leaf edge where the key belongs.

0 commit comments

Comments
 (0)