@@ -54,10 +54,8 @@ pub const CAPACITY: usize = 2 * B - 1;
5454/// `NodeHeader` because we do not want unnecessary padding between `len` and the keys. 
5555/// Crucially, `NodeHeader` can be safely transmuted to different K and V. (This is exploited 
5656/// by `as_header`.) 
57- /// See `into_key_slice` for an explanation of K2. K2 cannot be safely transmuted around 
58- /// because the size of `NodeHeader` depends on its alignment! 
5957#[ repr( C ) ]  
60- struct  NodeHeader < K ,  V ,   K2  =  ( ) >  { 
58+ struct  NodeHeader < K ,  V >  { 
6159    /// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`. 
6260     /// This either points to an actual node or is null. 
6361     parent :  * const  InternalNode < K ,  V > , 
@@ -72,9 +70,6 @@ struct NodeHeader<K, V, K2 = ()> {
7270     /// This next to `parent_idx` to encourage the compiler to join `len` and 
7371     /// `parent_idx` into the same 32-bit word, reducing space overhead. 
7472     len :  u16 , 
75- 
76-     /// See `into_key_slice`. 
77-      keys_start :  [ K2 ;  0 ] , 
7873} 
7974#[ repr( C ) ]  
8075struct  LeafNode < K ,  V >  { 
@@ -128,7 +123,7 @@ unsafe impl Sync for NodeHeader<(), ()> {}
128123// We use just a header in order to save space, since no operation on an empty tree will 
129124// ever take a pointer past the first key. 
130125static  EMPTY_ROOT_NODE :  NodeHeader < ( ) ,  ( ) >  =
131-     NodeHeader  {  parent :  ptr:: null ( ) ,  parent_idx :  MaybeUninit :: uninit ( ) ,  len :  0 ,   keys_start :   [ ]  } ; 
126+     NodeHeader  {  parent :  ptr:: null ( ) ,  parent_idx :  MaybeUninit :: uninit ( ) ,  len :  0  } ; 
132127
133128/// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden 
134129/// behind `BoxedNode`s to prevent dropping uninitialized keys and values. Any pointer to an 
@@ -390,14 +385,13 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
390385    } 
391386
392387    /// Borrows a view into the keys stored in the node. 
393-      /// Works on all possible nodes, including  the shared root. 
394-      pub  fn  keys ( & self )  -> & [ K ]  { 
388+      /// The caller must ensure that the node is not  the shared root. 
389+      pub  unsafe   fn  keys ( & self )  -> & [ K ]  { 
395390        self . reborrow ( ) . into_key_slice ( ) 
396391    } 
397392
398393    /// Borrows a view into the values stored in the node. 
399394     /// The caller must ensure that the node is not the shared root. 
400-      /// This function is not public, so doesn't have to support shared roots like `keys` does. 
401395     fn  vals ( & self )  -> & [ V ]  { 
402396        self . reborrow ( ) . into_val_slice ( ) 
403397    } 
@@ -515,7 +509,6 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
515509    } 
516510
517511    /// The caller must ensure that the node is not the shared root. 
518-      /// This function is not public, so doesn't have to support shared roots like `keys` does. 
519512     fn  keys_mut ( & mut  self )  -> & mut  [ K ]  { 
520513        unsafe  {  self . reborrow_mut ( ) . into_key_slice_mut ( )  } 
521514    } 
@@ -527,48 +520,11 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
527520} 
528521
529522impl < ' a ,  K :  ' a ,  V :  ' a ,  Type >  NodeRef < marker:: Immut < ' a > ,  K ,  V ,  Type >  { 
530-     fn  into_key_slice ( self )  -> & ' a  [ K ]  { 
531-         // We have to be careful here because we might be pointing to the shared root. 
532-         // In that case, we must not create an `&LeafNode`.  We could just return 
533-         // an empty slice whenever the length is 0 (this includes the shared root), 
534-         // but we want to avoid that run-time check. 
535-         // Instead, we create a slice pointing into the node whenever possible. 
536-         // We can sometimes do this even for the shared root, as the slice will be 
537-         // empty and `NodeHeader` contains an empty `keys_start` array. 
538-         // We cannot *always* do this because: 
539-         // - `keys_start` is not correctly typed because we want `NodeHeader`'s size to 
540-         //   not depend on the alignment of `K` (needed because `as_header` should be safe). 
541-         //   For this reason, `NodeHeader` has this `K2` parameter (that's usually `()` 
542-         //   and hence just adds a size-0-align-1 field, not affecting layout). 
543-         //   If the correctly typed header is more highly aligned than the allocated header, 
544-         //   we cannot transmute safely. 
545-         // - Even if we can transmute, the offset of a correctly typed `keys_start` might 
546-         //   be different and outside the bounds of the allocated header! 
547-         // So we do an alignment check and a size check first, that will be evaluated 
548-         // at compile-time, and only do any run-time check in the rare case that 
549-         // the compile-time checks signal danger. 
550-         if  ( mem:: align_of :: < NodeHeader < K ,  V ,  K > > ( )  > mem:: align_of :: < NodeHeader < K ,  V > > ( ) 
551-             || mem:: size_of :: < NodeHeader < K ,  V ,  K > > ( )  != mem:: size_of :: < NodeHeader < K ,  V > > ( ) ) 
552-             && self . is_shared_root ( ) 
553-         { 
554-             & [ ] 
555-         }  else  { 
556-             // If we are a `LeafNode<K, V>`, we can always transmute to 
557-             // `NodeHeader<K, V, K>` and `keys_start` always has the same offset 
558-             // as the actual `keys`. 
559-             // Thanks to the checks above, we know that we can transmute to 
560-             // `NodeHeader<K, V, K>` and that `keys_start` will be 
561-             // in-bounds of some allocation even if this is the shared root! 
562-             // (We might be one-past-the-end, but that is allowed by LLVM.) 
563-             // Thus we can use `NodeHeader<K, V, K>` 
564-             // to compute the pointer where the keys start. 
565-             // This entire hack will become unnecessary once 
566-             // <https://github.com/rust-lang/rfcs/pull/2582> lands, then we can just take a raw 
567-             // pointer to the `keys` field of `*const InternalNode<K, V>`. 
568-             let  header = self . as_header ( )  as  * const  _  as  * const  NodeHeader < K ,  V ,  K > ; 
569-             let  keys = unsafe  {  & ( * header) . keys_start  as  * const  _  as  * const  K  } ; 
570-             unsafe  {  slice:: from_raw_parts ( keys,  self . len ( ) )  } 
571-         } 
523+     /// The caller must ensure that the node is not the shared root. 
524+      unsafe  fn  into_key_slice ( self )  -> & ' a  [ K ]  { 
525+         debug_assert ! ( !self . is_shared_root( ) ) ; 
526+         // We cannot be the shared root, so `as_leaf` is okay. 
527+         slice:: from_raw_parts ( MaybeUninit :: first_ptr ( & self . as_leaf ( ) . keys ) ,  self . len ( ) ) 
572528    } 
573529
574530    /// The caller must ensure that the node is not the shared root. 
@@ -578,9 +534,10 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
578534        unsafe  {  slice:: from_raw_parts ( MaybeUninit :: first_ptr ( & self . as_leaf ( ) . vals ) ,  self . len ( ) )  } 
579535    } 
580536
537+     /// The caller must ensure that the node is not the shared root. 
581538     fn  into_slices ( self )  -> ( & ' a  [ K ] ,  & ' a  [ V ] )  { 
582539        let  k = unsafe  {  ptr:: read ( & self )  } ; 
583-         ( k. into_key_slice ( ) ,  self . into_val_slice ( ) ) 
540+         ( unsafe   {   k. into_key_slice ( )   } ,  self . into_val_slice ( ) ) 
584541    } 
585542} 
586543
0 commit comments