@@ -238,7 +238,7 @@ use core::{
238
238
marker:: PhantomData ,
239
239
mem:: MaybeUninit ,
240
240
ops:: { Deref , DerefMut } ,
241
- ptr,
241
+ ptr:: { self , NonNull } ,
242
242
} ;
243
243
244
244
pub use stack:: Node ;
@@ -294,6 +294,11 @@ impl<T> Pool<T> {
294
294
/// *NOTE:* This method does *not* have bounded execution time because it contains a CAS loop
295
295
pub fn alloc ( & self ) -> Option < Box < T , Uninit > > {
296
296
if mem:: size_of :: < T > ( ) == 0 {
297
+ // NOTE because we return a dangling pointer to a NODE, which has non-zero size
298
+ // even when T is a ZST, in this case we need to make sure we
299
+ // - don't do pointer arithmetic on this pointer
300
+ // - dereference that offset-ed pointer as a ZST
301
+ // because miri doesn't like that
297
302
return Some ( Box {
298
303
node : Ptr :: dangling ( ) ,
299
304
_state : PhantomData ,
@@ -320,8 +325,14 @@ impl<T> Pool<T> {
320
325
S : ' static ,
321
326
{
322
327
if TypeId :: of :: < S > ( ) == TypeId :: of :: < Init > ( ) {
328
+ let p = if mem:: size_of :: < T > ( ) == 0 {
329
+ // any pointer will do to invoke the destructor of a ZST
330
+ NonNull :: dangling ( ) . as_ptr ( )
331
+ } else {
332
+ unsafe { value. node . as_ref ( ) . data . get ( ) }
333
+ } ;
323
334
unsafe {
324
- ptr:: drop_in_place ( value . node . as_ref ( ) . data . get ( ) ) ;
335
+ ptr:: drop_in_place ( p ) ;
325
336
}
326
337
}
327
338
@@ -339,13 +350,12 @@ impl<T> Pool<T> {
339
350
///
340
351
/// This method returns the number of *new* blocks that can be allocated.
341
352
pub fn grow ( & self , memory : & ' static mut [ u8 ] ) -> usize {
342
- let sz = mem:: size_of :: < Node < T > > ( ) ;
343
-
344
- if sz == 0 {
345
- // SZT use no memory so a pool of SZT always has maximum capacity
353
+ if mem:: size_of :: < T > ( ) == 0 {
354
+ // ZST use no memory so a pool of ZST always has maximum capacity
346
355
return usize:: max_value ( ) ;
347
356
}
348
357
358
+ let sz = mem:: size_of :: < Node < T > > ( ) ;
349
359
let mut p = memory. as_mut_ptr ( ) ;
350
360
let mut len = memory. len ( ) ;
351
361
@@ -428,8 +438,14 @@ pub struct Box<T, STATE = Init> {
428
438
impl < T > Box < T , Uninit > {
429
439
/// Initializes this memory block
430
440
pub fn init ( self , val : T ) -> Box < T , Init > {
431
- unsafe {
432
- ptr:: write ( self . node . as_ref ( ) . data . get ( ) , val) ;
441
+ if mem:: size_of :: < T > ( ) == 0 {
442
+ // no memory operation needed for ZST
443
+ // BUT we want to avoid calling `val`s destructor
444
+ mem:: forget ( val)
445
+ } else {
446
+ unsafe {
447
+ ptr:: write ( self . node . as_ref ( ) . data . get ( ) , val) ;
448
+ }
433
449
}
434
450
435
451
Box {
@@ -473,13 +489,23 @@ impl<T> Deref for Box<T> {
473
489
type Target = T ;
474
490
475
491
fn deref ( & self ) -> & T {
476
- unsafe { & * self . node . as_ref ( ) . data . get ( ) }
492
+ if mem:: size_of :: < T > ( ) == 0 {
493
+ // any pointer will do for ZST
494
+ unsafe { & * NonNull :: dangling ( ) . as_ptr ( ) }
495
+ } else {
496
+ unsafe { & * self . node . as_ref ( ) . data . get ( ) }
497
+ }
477
498
}
478
499
}
479
500
480
501
impl < T > DerefMut for Box < T > {
481
502
fn deref_mut ( & mut self ) -> & mut T {
482
- unsafe { & mut * self . node . as_ref ( ) . data . get ( ) }
503
+ if mem:: size_of :: < T > ( ) == 0 {
504
+ // any pointer will do for ZST
505
+ unsafe { & mut * NonNull :: dangling ( ) . as_ptr ( ) }
506
+ } else {
507
+ unsafe { & mut * self . node . as_ref ( ) . data . get ( ) }
508
+ }
483
509
}
484
510
}
485
511
0 commit comments