diff --git a/crossbeam-channel/src/flavors/list.rs b/crossbeam-channel/src/flavors/list.rs index 9bda6d1cc..981e5e20a 100644 --- a/crossbeam-channel/src/flavors/list.rs +++ b/crossbeam-channel/src/flavors/list.rs @@ -49,6 +49,11 @@ struct Slot { } impl Slot { + const UNINIT: Self = Self { + msg: UnsafeCell::new(MaybeUninit::uninit()), + state: AtomicUsize::new(0), + }; + /// Waits until a message is written into the slot. fn wait_write(&self) { let backoff = Backoff::new(); @@ -72,13 +77,10 @@ struct Block { impl Block { /// Creates an empty block. fn new() -> Block { - // SAFETY: This is safe because: - // [1] `Block::next` (AtomicPtr) may be safely zero initialized. - // [2] `Block::slots` (Array) may be safely zero initialized because of [3, 4]. - // [3] `Slot::msg` (UnsafeCell) may be safely zero initialized because it - // holds a MaybeUninit. - // [4] `Slot::state` (AtomicUsize) may be safely zero initialized. - unsafe { MaybeUninit::zeroed().assume_init() } + Self { + next: AtomicPtr::new(ptr::null_mut()), + slots: [Slot::UNINIT; BLOCK_CAP], + } } /// Waits until the next pointer is set. diff --git a/crossbeam-deque/src/deque.rs b/crossbeam-deque/src/deque.rs index 2d496ec05..302819b34 100644 --- a/crossbeam-deque/src/deque.rs +++ b/crossbeam-deque/src/deque.rs @@ -1119,6 +1119,11 @@ struct Slot { } impl Slot { + const UNINIT: Self = Self { + task: UnsafeCell::new(MaybeUninit::uninit()), + state: AtomicUsize::new(0), + }; + /// Waits until a task is written into the slot. fn wait_write(&self) { let backoff = Backoff::new(); @@ -1142,13 +1147,10 @@ struct Block { impl Block { /// Creates an empty block that starts at `start_index`. fn new() -> Block { - // SAFETY: This is safe because: - // [1] `Block::next` (AtomicPtr) may be safely zero initialized. - // [2] `Block::slots` (Array) may be safely zero initialized because of [3, 4]. - // [3] `Slot::task` (UnsafeCell) may be safely zero initialized because it - // holds a MaybeUninit. - // [4] `Slot::state` (AtomicUsize) may be safely zero initialized. - unsafe { MaybeUninit::zeroed().assume_init() } + Self { + next: AtomicPtr::new(ptr::null_mut()), + slots: [Slot::UNINIT; BLOCK_CAP], + } } /// Waits until the next pointer is set. diff --git a/crossbeam-epoch/src/deferred.rs b/crossbeam-epoch/src/deferred.rs index c33d51502..54b5e2e96 100644 --- a/crossbeam-epoch/src/deferred.rs +++ b/crossbeam-epoch/src/deferred.rs @@ -29,6 +29,15 @@ impl fmt::Debug for Deferred { } impl Deferred { + pub(crate) const NO_OP: Self = { + fn no_op_call(_raw: *mut u8) {} + Self { + call: no_op_call, + data: MaybeUninit::uninit(), + _marker: PhantomData, + } + }; + /// Constructs a new `Deferred` from a `FnOnce()`. pub(crate) fn new(f: F) -> Self { let size = mem::size_of::(); diff --git a/crossbeam-epoch/src/internal.rs b/crossbeam-epoch/src/internal.rs index 44e1e8bbd..a6db79fbd 100644 --- a/crossbeam-epoch/src/internal.rs +++ b/crossbeam-epoch/src/internal.rs @@ -106,87 +106,11 @@ impl Bag { } impl Default for Bag { - #[rustfmt::skip] fn default() -> Self { - // TODO: [no_op; MAX_OBJECTS] syntax blocked by https://github.com/rust-lang/rust/issues/49147 - #[cfg(not(crossbeam_sanitize))] - return Bag { + Bag { len: 0, - deferreds: [ - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - ], - }; - #[cfg(crossbeam_sanitize)] - return Bag { - len: 0, - deferreds: [ - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - Deferred::new(no_op_func), - ], - }; + deferreds: [Deferred::NO_OP; MAX_OBJECTS], + } } } @@ -194,7 +118,7 @@ impl Drop for Bag { fn drop(&mut self) { // Call all deferred functions. for deferred in &mut self.deferreds[..self.len] { - let no_op = Deferred::new(no_op_func); + let no_op = Deferred::NO_OP; let owned_deferred = mem::replace(deferred, no_op); owned_deferred.call(); } @@ -210,8 +134,6 @@ impl fmt::Debug for Bag { } } -fn no_op_func() {} - /// A pair of an epoch and a bag. #[derive(Default, Debug)] struct SealedBag { diff --git a/crossbeam-queue/src/seg_queue.rs b/crossbeam-queue/src/seg_queue.rs index aed51717d..2761dc07c 100644 --- a/crossbeam-queue/src/seg_queue.rs +++ b/crossbeam-queue/src/seg_queue.rs @@ -35,6 +35,11 @@ struct Slot { } impl Slot { + const UNINIT: Self = Self { + value: UnsafeCell::new(MaybeUninit::uninit()), + state: AtomicUsize::new(0), + }; + /// Waits until a value is written into the slot. fn wait_write(&self) { let backoff = Backoff::new(); @@ -58,13 +63,10 @@ struct Block { impl Block { /// Creates an empty block that starts at `start_index`. fn new() -> Block { - // SAFETY: This is safe because: - // [1] `Block::next` (AtomicPtr) may be safely zero initialized. - // [2] `Block::slots` (Array) may be safely zero initialized because of [3, 4]. - // [3] `Slot::value` (UnsafeCell) may be safely zero initialized because it - // holds a MaybeUninit. - // [4] `Slot::state` (AtomicUsize) may be safely zero initialized. - unsafe { MaybeUninit::zeroed().assume_init() } + Self { + next: AtomicPtr::new(ptr::null_mut()), + slots: [Slot::UNINIT; BLOCK_CAP], + } } /// Waits until the next pointer is set. diff --git a/crossbeam-utils/src/atomic/atomic_cell.rs b/crossbeam-utils/src/atomic/atomic_cell.rs index 164084b9f..8d46a58b3 100644 --- a/crossbeam-utils/src/atomic/atomic_cell.rs +++ b/crossbeam-utils/src/atomic/atomic_cell.rs @@ -902,12 +902,7 @@ fn lock(addr: usize) -> &'static SeqLock { const LEN: usize = 97; #[allow(clippy::declare_interior_mutable_const)] const L: SeqLock = SeqLock::new(); - static LOCKS: [SeqLock; LEN] = [ - L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, - L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, - L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, - L, L, L, L, L, L, L, - ]; + static LOCKS: [SeqLock; LEN] = [L; LEN]; // If the modulus is a constant number, the compiler will use crazy math to transform this into // a sequence of cheap arithmetic operations rather than using the slow modulo instruction.