@@ -257,8 +257,8 @@ fn calculate_layout<T>(buckets: usize) -> Option<(Layout, usize)> {
257257/// is a ZST, then we instead track the index of the element in the table so
258258/// that `erase` works properly.
259259pub struct Bucket < T > {
260- // Using *const for variance
261- ptr : * const T ,
260+ // Using `NonNull` for variance and niche layout
261+ ptr : NonNull < T > ,
262262}
263263
264264// This Send impl is needed for rayon support. This is safe since Bucket is
@@ -274,31 +274,44 @@ impl<T> Clone for Bucket<T> {
274274
275275impl < T > Bucket < T > {
276276 #[ cfg_attr( feature = "inline-more" , inline) ]
277- unsafe fn from_base_index ( base : * const T , index : usize ) -> Self {
277+ unsafe fn from_base_index ( base : NonNull < T > , index : usize ) -> Self {
278278 let ptr = if mem:: size_of :: < T > ( ) == 0 {
279- index as * const T
279+ // won't overflow because index must be less than length
280+ ( index + 1 ) as * mut T
280281 } else {
281- base. add ( index)
282+ base. as_ptr ( ) . add ( index)
282283 } ;
283- Self { ptr }
284+ Self {
285+ ptr : NonNull :: new_unchecked ( ptr) ,
286+ }
287+ }
288+ #[ cfg_attr( feature = "inline-more" , inline) ]
289+ unsafe fn to_base_index ( & self , base : NonNull < T > ) -> usize {
290+ if mem:: size_of :: < T > ( ) == 0 {
291+ self . ptr . as_ptr ( ) as usize - 1
292+ } else {
293+ offset_from ( self . ptr . as_ptr ( ) , base. as_ptr ( ) )
294+ }
284295 }
285296 #[ cfg_attr( feature = "inline-more" , inline) ]
286297 pub unsafe fn as_ptr ( & self ) -> * mut T {
287298 if mem:: size_of :: < T > ( ) == 0 {
288299 // Just return an arbitrary ZST pointer which is properly aligned
289300 mem:: align_of :: < T > ( ) as * mut T
290301 } else {
291- self . ptr as * mut T
302+ self . ptr . as_ptr ( )
292303 }
293304 }
294305 #[ cfg_attr( feature = "inline-more" , inline) ]
295306 unsafe fn add ( & self , offset : usize ) -> Self {
296307 let ptr = if mem:: size_of :: < T > ( ) == 0 {
297- ( self . ptr as usize + offset) as * const T
308+ ( self . ptr . as_ptr ( ) as usize + offset) as * mut T
298309 } else {
299- self . ptr . add ( offset)
310+ self . ptr . as_ptr ( ) . add ( offset)
300311 } ;
301- Self { ptr }
312+ Self {
313+ ptr : NonNull :: new_unchecked ( ptr) ,
314+ }
302315 }
303316 #[ cfg_attr( feature = "inline-more" , inline) ]
304317 pub unsafe fn drop ( & self ) {
@@ -428,11 +441,7 @@ impl<T> RawTable<T> {
428441 /// Returns the index of a bucket from a `Bucket`.
429442 #[ cfg_attr( feature = "inline-more" , inline) ]
430443 pub unsafe fn bucket_index ( & self , bucket : & Bucket < T > ) -> usize {
431- if mem:: size_of :: < T > ( ) == 0 {
432- bucket. ptr as usize
433- } else {
434- offset_from ( bucket. ptr , self . data . as_ptr ( ) )
435- }
444+ bucket. to_base_index ( self . data )
436445 }
437446
438447 /// Returns a pointer to a control byte.
@@ -447,7 +456,7 @@ impl<T> RawTable<T> {
447456 pub unsafe fn bucket ( & self , index : usize ) -> Bucket < T > {
448457 debug_assert_ne ! ( self . bucket_mask, 0 ) ;
449458 debug_assert ! ( index < self . buckets( ) ) ;
450- Bucket :: from_base_index ( self . data . as_ptr ( ) , index)
459+ Bucket :: from_base_index ( self . data , index)
451460 }
452461
453462 /// Erases an element from the table without dropping it.
@@ -936,7 +945,7 @@ impl<T> RawTable<T> {
936945 /// struct, we have to make the `iter` method unsafe.
937946 #[ cfg_attr( feature = "inline-more" , inline) ]
938947 pub unsafe fn iter ( & self ) -> RawIter < T > {
939- let data = Bucket :: from_base_index ( self . data . as_ptr ( ) , 0 ) ;
948+ let data = Bucket :: from_base_index ( self . data , 0 ) ;
940949 RawIter {
941950 iter : RawIterRange :: new ( self . ctrl . as_ptr ( ) , data, self . buckets ( ) ) ,
942951 items : self . items ,
0 commit comments