@@ -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
@@ -428,8 +439,14 @@ pub struct Box<T, STATE = Init> {
428
439
impl < T > Box < T , Uninit > {
429
440
/// Initializes this memory block
430
441
pub fn init ( self , val : T ) -> Box < T , Init > {
431
- unsafe {
432
- ptr:: write ( self . node . as_ref ( ) . data . get ( ) , val) ;
442
+ if mem:: size_of :: < T > ( ) == 0 {
443
+ // no memory operation needed for ZST
444
+ // BUT we want to avoid calling `val`s destructor
445
+ mem:: forget ( val)
446
+ } else {
447
+ unsafe {
448
+ ptr:: write ( self . node . as_ref ( ) . data . get ( ) , val) ;
449
+ }
433
450
}
434
451
435
452
Box {
@@ -473,13 +490,23 @@ impl<T> Deref for Box<T> {
473
490
type Target = T ;
474
491
475
492
fn deref ( & self ) -> & T {
476
- unsafe { & * self . node . as_ref ( ) . data . get ( ) }
493
+ if mem:: size_of :: < T > ( ) == 0 {
494
+ // any pointer will do for ZST
495
+ unsafe { & * NonNull :: dangling ( ) . as_ptr ( ) }
496
+ } else {
497
+ unsafe { & * self . node . as_ref ( ) . data . get ( ) }
498
+ }
477
499
}
478
500
}
479
501
480
502
impl < T > DerefMut for Box < T > {
481
503
fn deref_mut ( & mut self ) -> & mut T {
482
- unsafe { & mut * self . node . as_ref ( ) . data . get ( ) }
504
+ if mem:: size_of :: < T > ( ) == 0 {
505
+ // any pointer will do for ZST
506
+ unsafe { & mut * NonNull :: dangling ( ) . as_ptr ( ) }
507
+ } else {
508
+ unsafe { & mut * self . node . as_ref ( ) . data . get ( ) }
509
+ }
483
510
}
484
511
}
485
512
0 commit comments