@@ -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.
120120type 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.
125125pub 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
159159impl < 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
174179impl < 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
280293unsafe impl < ' a , K : Send + ' a , V : Send + ' a , Type > Send for NodeRef < marker:: Mut < ' a > , K , V , Type > { }
281294unsafe impl < ' a , K : Send + ' a , V : Send + ' a , Type > Send for NodeRef < marker:: ValMut < ' a > , K , V , Type > { }
282295unsafe 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
284298impl < 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}
0 commit comments