diff --git a/src/rb/local.rs b/src/rb/local.rs index 1145d52..c2d383e 100644 --- a/src/rb/local.rs +++ b/src/rb/local.rs @@ -25,7 +25,7 @@ struct End { } impl End { - fn new(index: usize) -> Self { + const fn new(index: usize) -> Self { Self { index: Cell::new(index), held: Cell::new(false), @@ -49,8 +49,9 @@ impl LocalRb { /// /// The items in storage inside `read..write` range must be initialized, items outside this range must be uninitialized. /// `read` and `write` positions must be valid (see implementation details). - pub unsafe fn from_raw_parts(storage: S, read: usize, write: usize) -> Self { - assert!(!storage.is_empty()); + /// + /// `storage` length must be non-zero. + pub const unsafe fn from_raw_parts(storage: S, read: usize, write: usize) -> Self { Self { storage, read: End::new(read), diff --git a/src/rb/macros.rs b/src/rb/macros.rs index 26251d3..8b698b6 100644 --- a/src/rb/macros.rs +++ b/src/rb/macros.rs @@ -2,7 +2,12 @@ macro_rules! rb_impl_init { ($type:ident) => { impl Default for $type> { fn default() -> Self { - unsafe { Self::from_raw_parts(crate::utils::uninit_array().into(), usize::default(), usize::default()) } + Self::new() + } + } + impl $type> { + pub const fn new() -> Self { + unsafe { Self::from_raw_parts(crate::storage::Array::new(crate::utils::uninit_array()), 0, 0) } } } diff --git a/src/rb/shared.rs b/src/rb/shared.rs index c73cba6..36cad99 100644 --- a/src/rb/shared.rs +++ b/src/rb/shared.rs @@ -59,8 +59,9 @@ impl SharedRb { /// /// The items in storage inside `read..write` range must be initialized, items outside this range must be uninitialized. /// `read` and `write` positions must be valid (see implementation details). - pub unsafe fn from_raw_parts(storage: S, read: usize, write: usize) -> Self { - assert!(!storage.is_empty()); + /// + /// `storage` length must be non-zero. + pub const unsafe fn from_raw_parts(storage: S, read: usize, write: usize) -> Self { Self { storage, read_index: CachePadded::new(AtomicUsize::new(read)), diff --git a/src/storage.rs b/src/storage.rs index bd504e9..c572eb6 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -93,6 +93,11 @@ pub struct Owning { unsafe impl Sync for Owning where T: Send {} impl From for Owning { fn from(value: T) -> Self { + Self::new(value) + } +} +impl Owning { + pub const fn new(value: T) -> Self { Self { data: UnsafeCell::new(value), } diff --git a/src/tests/new.rs b/src/tests/new.rs index 7c17f3f..4cf6dda 100644 --- a/src/tests/new.rs +++ b/src/tests/new.rs @@ -3,6 +3,9 @@ use crate::{storage::Array, traits::*}; #[cfg(feature = "alloc")] use alloc::vec::Vec; +#[allow(clippy::declare_interior_mutable_const)] +const _RB: Rb> = Rb::>::new(); + #[test] fn new_static() { let rb = Rb::>::default(); diff --git a/src/utils.rs b/src/utils.rs index e70e05b..14fb185 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -6,7 +6,7 @@ use core::{ }; // TODO: Remove on `maybe_uninit_uninit_array` stabilization. -pub fn uninit_array() -> [MaybeUninit; N] { +pub const fn uninit_array() -> [MaybeUninit; N] { unsafe { MaybeUninit::<[MaybeUninit; N]>::uninit().assume_init() } } @@ -39,21 +39,20 @@ pub fn move_uninit_slice(dst: &mut [MaybeUninit], src: &[MaybeUninit]) } pub fn array_to_uninit(value: [T; N]) -> [MaybeUninit; N] { - let value = mem::ManuallyDrop::new(value); - let ptr = &value as *const _ as *const [MaybeUninit; N]; - unsafe { ptr.read() } + let value = MaybeUninit::new(value); + let this = &value as *const _ as *const [MaybeUninit; N]; + unsafe { this.read() } } #[cfg(feature = "alloc")] -pub fn vec_to_uninit(value: Vec) -> Vec> { - let value = mem::ManuallyDrop::new(value); - let ptr = &value as *const _ as *const Vec>; - unsafe { ptr.read() } +pub fn vec_to_uninit(mut value: Vec) -> Vec> { + let (ptr, len, cap) = (value.as_mut_ptr() as *mut MaybeUninit, value.len(), value.capacity()); + mem::forget(value); + unsafe { Vec::from_raw_parts(ptr, len, cap) } } #[cfg(feature = "alloc")] pub fn boxed_slice_to_uninit(value: Box<[T]>) -> Box<[MaybeUninit]> { - let value = mem::ManuallyDrop::new(value); - let ptr = &value as *const _ as *const Box<[MaybeUninit]>; - unsafe { ptr.read() } + let ptr = Box::into_raw(value) as *mut [MaybeUninit]; + unsafe { Box::from_raw(ptr) } }