@@ -257,8 +257,8 @@ fn calculate_layout<T>(buckets: usize) -> Option<(Layout, usize)> {
257
257
/// is a ZST, then we instead track the index of the element in the table so
258
258
/// that `erase` works properly.
259
259
pub struct Bucket < T > {
260
- // Using *const for variance
261
- ptr : * const T ,
260
+ // Using `NonNull` for variance and niche layout
261
+ ptr : NonNull < T > ,
262
262
}
263
263
264
264
// This Send impl is needed for rayon support. This is safe since Bucket is
@@ -274,31 +274,44 @@ impl<T> Clone for Bucket<T> {
274
274
275
275
impl < T > Bucket < T > {
276
276
#[ 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 {
278
278
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
280
281
} else {
281
- base. add ( index)
282
+ base. as_ptr ( ) . add ( index)
282
283
} ;
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
+ }
284
295
}
285
296
#[ cfg_attr( feature = "inline-more" , inline) ]
286
297
pub unsafe fn as_ptr ( & self ) -> * mut T {
287
298
if mem:: size_of :: < T > ( ) == 0 {
288
299
// Just return an arbitrary ZST pointer which is properly aligned
289
300
mem:: align_of :: < T > ( ) as * mut T
290
301
} else {
291
- self . ptr as * mut T
302
+ self . ptr . as_ptr ( )
292
303
}
293
304
}
294
305
#[ cfg_attr( feature = "inline-more" , inline) ]
295
306
unsafe fn add ( & self , offset : usize ) -> Self {
296
307
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
298
309
} else {
299
- self . ptr . add ( offset)
310
+ self . ptr . as_ptr ( ) . add ( offset)
300
311
} ;
301
- Self { ptr }
312
+ Self {
313
+ ptr : NonNull :: new_unchecked ( ptr) ,
314
+ }
302
315
}
303
316
#[ cfg_attr( feature = "inline-more" , inline) ]
304
317
pub unsafe fn drop ( & self ) {
@@ -428,11 +441,7 @@ impl<T> RawTable<T> {
428
441
/// Returns the index of a bucket from a `Bucket`.
429
442
#[ cfg_attr( feature = "inline-more" , inline) ]
430
443
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 )
436
445
}
437
446
438
447
/// Returns a pointer to a control byte.
@@ -447,7 +456,7 @@ impl<T> RawTable<T> {
447
456
pub unsafe fn bucket ( & self , index : usize ) -> Bucket < T > {
448
457
debug_assert_ne ! ( self . bucket_mask, 0 ) ;
449
458
debug_assert ! ( index < self . buckets( ) ) ;
450
- Bucket :: from_base_index ( self . data . as_ptr ( ) , index)
459
+ Bucket :: from_base_index ( self . data , index)
451
460
}
452
461
453
462
/// Erases an element from the table without dropping it.
@@ -936,7 +945,7 @@ impl<T> RawTable<T> {
936
945
/// struct, we have to make the `iter` method unsafe.
937
946
#[ cfg_attr( feature = "inline-more" , inline) ]
938
947
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 ) ;
940
949
RawIter {
941
950
iter : RawIterRange :: new ( self . ctrl . as_ptr ( ) , data, self . buckets ( ) ) ,
942
951
items : self . items ,
0 commit comments