5050 P : Pointer ,
5151 T : Tag ,
5252{
53+ pub fn new ( pointer : P , tag : T ) -> Self {
54+ Self { packed : Self :: pack ( P :: into_ptr ( pointer) , tag) , data : PhantomData }
55+ }
56+
5357 const TAG_BIT_SHIFT : usize = usize:: BITS as usize - T :: BITS ;
5458 const ASSERTION : ( ) = {
5559 assert ! ( T :: BITS <= P :: BITS ) ;
@@ -58,28 +62,28 @@ where
5862 assert ! ( std:: mem:: size_of:: <& P :: Target >( ) == std:: mem:: size_of:: <usize >( ) ) ;
5963 } ;
6064
61- pub fn new ( pointer : P , tag : T ) -> Self {
65+ /// Pack pointer `ptr` that comes from [`P::into_ptr`] with a `tag`.
66+ ///
67+ /// [`P::into_ptr`]: Pointer::into_ptr
68+ fn pack ( ptr : NonNull < P :: Target > , tag : T ) -> NonNull < P :: Target > {
6269 // Trigger assert!
6370 let ( ) = Self :: ASSERTION ;
6471
6572 let packed_tag = tag. into_usize ( ) << Self :: TAG_BIT_SHIFT ;
6673
67- Self {
68- packed : P :: into_ptr ( pointer) . map_addr ( |addr| {
69- // SAFETY:
70- // - The pointer is `NonNull` => it's address is `NonZeroUsize`
71- // - `P::BITS` least significant bits are always zero (`Pointer` contract)
72- // - `T::BITS <= P::BITS` (from `Self::ASSERTION`)
73- //
74- // Thus `addr >> T::BITS` is guaranteed to be non-zero.
75- //
76- // `{non_zero} | packed_tag` can't make the value zero.
77-
78- let packed = ( addr. get ( ) >> T :: BITS ) | packed_tag;
79- unsafe { NonZeroUsize :: new_unchecked ( packed) }
80- } ) ,
81- data : PhantomData ,
82- }
74+ ptr. map_addr ( |addr| {
75+ // SAFETY:
76+ // - The pointer is `NonNull` => it's address is `NonZeroUsize`
77+ // - `P::BITS` least significant bits are always zero (`Pointer` contract)
78+ // - `T::BITS <= P::BITS` (from `Self::ASSERTION`)
79+ //
80+ // Thus `addr >> T::BITS` is guaranteed to be non-zero.
81+ //
82+ // `{non_zero} | packed_tag` can't make the value zero.
83+
84+ let packed = ( addr. get ( ) >> T :: BITS ) | packed_tag;
85+ unsafe { NonZeroUsize :: new_unchecked ( packed) }
86+ } )
8387 }
8488
8589 pub ( super ) fn pointer_raw ( & self ) -> NonNull < P :: Target > {
@@ -117,12 +121,7 @@ where
117121
118122 #[ inline]
119123 pub fn set_tag ( & mut self , tag : T ) {
120- // TODO: refactor packing into a function and reuse it here
121- let new_tag = T :: into_usize ( tag) << Self :: TAG_BIT_SHIFT ;
122- let tag_mask = ( 1 << T :: BITS ) - 1 ;
123- self . packed = self . packed . map_addr ( |addr| unsafe {
124- NonZeroUsize :: new_unchecked ( addr. get ( ) & !( tag_mask << Self :: TAG_BIT_SHIFT ) | new_tag)
125- } ) ;
124+ self . packed = Self :: pack ( self . pointer_raw ( ) , tag) ;
126125 }
127126}
128127
0 commit comments