@@ -93,8 +93,8 @@ struct InternalNode<K, V> {
93
93
data : LeafNode < K , V > ,
94
94
95
95
/// 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 .
98
98
edges : [ MaybeUninit < BoxedNode < K , V > > ; 2 * B ] ,
99
99
}
100
100
@@ -119,7 +119,7 @@ impl<K, V> InternalNode<K, V> {
119
119
/// is not a separate type and has no destructor.
120
120
type BoxedNode < K , V > = NonNull < LeafNode < K , V > > ;
121
121
122
- /// An owned tree.
122
+ /// The root node of an owned tree.
123
123
///
124
124
/// Note that this does not have a destructor, and must be cleaned up manually.
125
125
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> {
157
157
}
158
158
159
159
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.
164
163
pub fn borrow_mut ( & mut self ) -> NodeRef < marker:: Mut < ' _ > , K , V , Type > {
165
164
NodeRef { height : self . height , node : self . node , _marker : PhantomData }
166
165
}
167
166
168
- /// Slightly mutably borrows the owned node.
167
+ /// Slightly mutably borrows the owned root node.
169
168
pub fn borrow_valmut ( & mut self ) -> NodeRef < marker:: ValMut < ' _ > , K , V , Type > {
170
169
NodeRef { height : self . height , node : self . node , _marker : PhantomData }
171
170
}
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
+ }
172
177
}
173
178
174
179
impl < K , V > NodeRef < marker:: Owned , K , V , marker:: LeafOrInternal > {
@@ -196,8 +201,13 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
196
201
197
202
let top = self . node ;
198
203
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 ;
201
211
self . clear_parent_link ( ) ;
202
212
203
213
unsafe {
@@ -224,6 +234,9 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
224
234
/// although insert methods allow a mutable pointer to a value to coexist.
225
235
/// - When this is `Owned`, the `NodeRef` acts roughly like `Box<Node>`,
226
236
/// 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.
227
240
/// Since any `NodeRef` allows navigating through the tree, `BorrowType`
228
241
/// effectively applies to the entire tree, not just to the node itself.
229
242
/// - `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
280
293
unsafe impl < ' a , K : Send + ' a , V : Send + ' a , Type > Send for NodeRef < marker:: Mut < ' a > , K , V , Type > { }
281
294
unsafe impl < ' a , K : Send + ' a , V : Send + ' a , Type > Send for NodeRef < marker:: ValMut < ' a > , K , V , Type > { }
282
295
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 > { }
283
297
284
298
impl < BorrowType , K , V > NodeRef < BorrowType , K , V , marker:: Internal > {
285
299
/// Unpack a node reference that was packed as `NodeRef::parent`.
@@ -343,7 +357,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
343
357
}
344
358
}
345
359
346
- impl < BorrowType , K , V , Type > NodeRef < BorrowType , K , V , Type > {
360
+ impl < BorrowType : marker :: BorrowType , K , V , Type > NodeRef < BorrowType , K , V , Type > {
347
361
/// Finds the parent of the current node. Returns `Ok(handle)` if the current
348
362
/// node actually has a parent, where `handle` points to the edge of the parent
349
363
/// 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> {
356
370
pub fn ascend (
357
371
self ,
358
372
) -> Result < Handle < NodeRef < BorrowType , K , V , marker:: Internal > , marker:: Edge > , Self > {
373
+ assert ! ( BorrowType :: PERMITS_TRAVERSAL ) ;
359
374
// We need to use raw pointers to nodes because, if BorrowType is marker::ValMut,
360
375
// there might be outstanding mutable references to values that we must not invalidate.
361
376
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> {
410
425
}
411
426
}
412
427
413
- impl < K , V > NodeRef < marker:: Owned , K , V , marker:: LeafOrInternal > {
428
+ impl < K , V > NodeRef < marker:: Dying , K , V , marker:: LeafOrInternal > {
414
429
/// Similar to `ascend`, gets a reference to a node's parent node, but also
415
430
/// deallocates the current node in the process. This is unsafe because the
416
431
/// current node will still be accessible despite being deallocated.
417
432
pub unsafe fn deallocate_and_ascend (
418
433
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 > > {
420
435
let height = self . height ;
421
436
let node = self . node ;
422
437
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
951
966
}
952
967
}
953
968
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
+ {
955
972
/// Finds the node pointed to by this edge.
956
973
///
957
974
/// The method name assumes you picture trees with the root node on top.
958
975
///
959
976
/// `edge.descend().ascend().unwrap()` and `node.ascend().unwrap().descend()` should
960
977
/// both, upon success, do nothing.
961
978
pub fn descend ( self ) -> NodeRef < BorrowType , K , V , marker:: LeafOrInternal > {
979
+ assert ! ( BorrowType :: PERMITS_TRAVERSAL ) ;
962
980
// We need to use raw pointers to nodes because, if BorrowType is
963
981
// marker::ValMut, there might be outstanding mutable references to
964
982
// values that we must not invalidate. There's no worry accessing the
@@ -1596,10 +1614,27 @@ pub mod marker {
1596
1614
pub enum LeafOrInternal { }
1597
1615
1598
1616
pub enum Owned { }
1617
+ pub enum Dying { }
1599
1618
pub struct Immut < ' a > ( PhantomData < & ' a ( ) > ) ;
1600
1619
pub struct Mut < ' a > ( PhantomData < & ' a mut ( ) > ) ;
1601
1620
pub struct ValMut < ' a > ( PhantomData < & ' a mut ( ) > ) ;
1602
1621
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
+
1603
1638
pub enum KV { }
1604
1639
pub enum Edge { }
1605
1640
}
0 commit comments