6
6
use core:: {
7
7
cell:: UnsafeCell ,
8
8
marker:: PhantomData ,
9
- num:: NonZeroU64 ,
9
+ num:: { NonZeroU32 , NonZeroU64 } ,
10
10
ptr:: NonNull ,
11
11
sync:: atomic:: { AtomicU64 , Ordering } ,
12
12
} ;
@@ -107,24 +107,28 @@ impl<T> Clone for Ptr<T> {
107
107
108
108
impl < T > Copy for Ptr < T > { }
109
109
110
+ fn initial_tag_value ( ) -> NonZeroU32 {
111
+ NonZeroU32 :: new ( 1 ) . unwrap ( )
112
+ }
113
+
110
114
impl < T > Ptr < T > {
111
115
#[ cfg( target_arch = "x86_64" ) ]
112
116
pub fn new ( p : * mut T ) -> Option < Self > {
113
117
use core:: convert:: TryFrom ;
114
118
115
119
i32:: try_from ( ( p as isize ) . wrapping_sub ( anchor :: < T > ( ) as isize ) )
116
120
. ok ( )
117
- . map ( |offset| unsafe { Ptr :: from_parts ( 0 , offset) } )
121
+ . map ( |offset| unsafe { Ptr :: from_parts ( initial_tag_value ( ) , offset) } )
118
122
}
119
123
120
124
#[ cfg( target_arch = "x86" ) ]
121
125
pub fn new ( p : * mut T ) -> Option < Self > {
122
- Some ( unsafe { Ptr :: from_parts ( 0 , p as i32 ) } )
126
+ Some ( unsafe { Ptr :: from_parts ( initial_tag_value ( ) , p as i32 ) } )
123
127
}
124
128
125
- unsafe fn from_parts ( tag : u32 , offset : i32 ) -> Self {
129
+ unsafe fn from_parts ( tag : NonZeroU32 , offset : i32 ) -> Self {
126
130
Self {
127
- inner : NonZeroU64 :: new_unchecked ( ( tag as u64 ) << 32 | ( offset as u32 as u64 ) ) ,
131
+ inner : NonZeroU64 :: new_unchecked ( ( tag. get ( ) as u64 ) << 32 | ( offset as u32 as u64 ) ) ,
128
132
_marker : PhantomData ,
129
133
}
130
134
}
@@ -140,12 +144,15 @@ impl<T> Ptr<T> {
140
144
self . inner . get ( )
141
145
}
142
146
143
- fn tag ( & self ) -> u32 {
144
- ( self . inner . get ( ) >> 32 ) as u32
147
+ fn tag ( & self ) -> NonZeroU32 {
148
+ let tag = ( self . inner . get ( ) >> 32 ) as u32 ;
149
+ debug_assert_ne ! ( 0 , tag, "broken non-zero invariant" ) ;
150
+ unsafe { NonZeroU32 :: new_unchecked ( tag) }
145
151
}
146
152
147
153
fn incr_tag ( & mut self ) {
148
- let tag = self . tag ( ) . wrapping_add ( 1 ) ;
154
+ let maybe_zero_tag = self . tag ( ) . get ( ) . wrapping_add ( 1 ) ;
155
+ let tag = NonZeroU32 :: new ( maybe_zero_tag) . unwrap_or ( initial_tag_value ( ) ) ;
149
156
let offset = self . offset ( ) ;
150
157
151
158
* self = unsafe { Ptr :: from_parts ( tag, offset) } ;
@@ -170,7 +177,7 @@ impl<T> Ptr<T> {
170
177
}
171
178
172
179
pub fn dangling ( ) -> Self {
173
- unsafe { Self :: from_parts ( 0 , 1 ) }
180
+ unsafe { Self :: from_parts ( initial_tag_value ( ) , 1 ) }
174
181
}
175
182
176
183
pub unsafe fn as_ref ( & self ) -> & T {
0 commit comments