Skip to content

Commit 3adc93a

Browse files
authored
Merge pull request #242 from japaric/fix-miri
fix miri errors
2 parents d3be154 + 8cf5a26 commit 3adc93a

File tree

3 files changed

+58
-16
lines changed

3 files changed

+58
-16
lines changed

src/pool/cas.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ impl<T> Ptr<T> {
183183
fn as_raw(&self) -> NonNull<T> {
184184
unsafe {
185185
NonNull::new_unchecked(
186-
(anchor::<T>(None) as *mut u8).offset(self.offset() as isize) as *mut T,
186+
(anchor::<T>(None) as isize).wrapping_add(self.offset() as isize) as *mut T,
187187
)
188188
}
189189
}

src/pool/mod.rs

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ use core::{
238238
marker::PhantomData,
239239
mem::MaybeUninit,
240240
ops::{Deref, DerefMut},
241-
ptr,
241+
ptr::{self, NonNull},
242242
};
243243

244244
pub use stack::Node;
@@ -294,6 +294,11 @@ impl<T> Pool<T> {
294294
/// *NOTE:* This method does *not* have bounded execution time because it contains a CAS loop
295295
pub fn alloc(&self) -> Option<Box<T, Uninit>> {
296296
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
297302
return Some(Box {
298303
node: Ptr::dangling(),
299304
_state: PhantomData,
@@ -320,8 +325,14 @@ impl<T> Pool<T> {
320325
S: 'static,
321326
{
322327
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+
};
323334
unsafe {
324-
ptr::drop_in_place(value.node.as_ref().data.get());
335+
ptr::drop_in_place(p);
325336
}
326337
}
327338

@@ -339,13 +350,12 @@ impl<T> Pool<T> {
339350
///
340351
/// This method returns the number of *new* blocks that can be allocated.
341352
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
346355
return usize::max_value();
347356
}
348357

358+
let sz = mem::size_of::<Node<T>>();
349359
let mut p = memory.as_mut_ptr();
350360
let mut len = memory.len();
351361

@@ -428,8 +438,14 @@ pub struct Box<T, STATE = Init> {
428438
impl<T> Box<T, Uninit> {
429439
/// Initializes this memory block
430440
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+
}
433449
}
434450

435451
Box {
@@ -473,13 +489,23 @@ impl<T> Deref for Box<T> {
473489
type Target = T;
474490

475491
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+
}
477498
}
478499
}
479500

480501
impl<T> DerefMut for Box<T> {
481502
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+
}
483509
}
484510
}
485511

src/pool/singleton.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use core::{
77
marker::PhantomData,
88
mem::{self, MaybeUninit},
99
ops::{Deref, DerefMut},
10-
ptr,
10+
ptr::{self, NonNull},
1111
};
1212

1313
use super::{Init, Node, Uninit};
@@ -109,8 +109,14 @@ where
109109

110110
mem::forget(self);
111111

112-
unsafe {
113-
ptr::write(node.as_ref().data.get(), val);
112+
if mem::size_of::<P::Data>() == 0 {
113+
// no memory operation needed for ZST
114+
// BUT we want to avoid calling `val`s destructor
115+
mem::forget(val)
116+
} else {
117+
unsafe {
118+
ptr::write(node.as_ref().data.get(), val);
119+
}
114120
}
115121

116122
Box {
@@ -167,7 +173,11 @@ where
167173
let node = self.inner.node;
168174

169175
mem::forget(self);
170-
mem::forget(unsafe { ptr::read(node.as_ref().data.get()) });
176+
if mem::size_of::<P::Data>() == 0 {
177+
// no need to do a pointer dereference in this case
178+
} else {
179+
mem::forget(unsafe { ptr::read(node.as_ref().data.get()) });
180+
}
171181

172182
Box {
173183
inner: super::Box {
@@ -228,8 +238,14 @@ where
228238
{
229239
fn drop(&mut self) {
230240
if TypeId::of::<S>() == TypeId::of::<Init>() {
241+
let p = if mem::size_of::<P::Data>() == 0 {
242+
// any pointer will do to invoke the destructor of a ZST
243+
NonNull::dangling().as_ptr()
244+
} else {
245+
unsafe { self.inner.node.as_ref().data.get() }
246+
};
231247
unsafe {
232-
ptr::drop_in_place(self.inner.node.as_ref().data.get());
248+
ptr::drop_in_place(p);
233249
}
234250
}
235251

0 commit comments

Comments
 (0)