diff --git a/src/__core.rs b/src/__core.rs index 001a802479..cb32e40532 100644 --- a/src/__core.rs +++ b/src/__core.rs @@ -1,36 +1,90 @@ /// Temporary fork of some stuff in `core` that's doesn't have a `const fn` API pub mod mem { - #[cfg(not(feature = "const-fn"))] - pub use core::mem::uninitialized; - pub use core::mem::{replace, zeroed, ManuallyDrop}; + pub use core::mem::{replace, zeroed, ManuallyDrop, uninitialized}; + use core::ops::{Deref, DerefMut}; + + + /// extremely unsafe uniniatilized memory + /// only use with ManuallyDrop + #[allow(unions_with_drop_fields)] + #[cfg(feature = "const-fn")] + pub(crate) union Uninit { + uninit: (), + init: T, + } + + #[cfg(feature = "const-fn")] + impl Uninit { + const_fn!( + pub const unsafe fn new() -> Self { + Uninit { + uninit: () + } + } + ); + } #[cfg(feature = "const-fn")] - pub const unsafe fn uninitialized() -> T { - #[allow(unions_with_drop_fields)] - union U { - none: (), - some: T, + impl Deref for Uninit { + type Target = T; + fn deref(&self) -> &T { + unsafe{ &self.init } } + } - U { none: () }.some + #[cfg(feature = "const-fn")] + impl DerefMut for Uninit { + fn deref_mut(&mut self) -> &mut T { + unsafe { &mut self.init } + } } + + /// extremely unsafe uniniatilized memory + /// only use with ManuallyDrop + #[cfg(not(feature = "const-fn"))] + pub(crate) struct Uninit(T); + + #[cfg(not(feature = "const-fn"))] + impl Uninit { + pub unsafe fn new() -> Self { + Uninit(uninitialized()) + } + } + + #[cfg(not(feature = "const-fn"))] + impl Deref for Uninit { + type Target = T; + fn deref(&self) -> &T { + &self.0 + } + } + + #[cfg(not(feature = "const-fn"))] + impl DerefMut for Uninit { + fn deref_mut(&mut self) -> &mut T { + &mut self.0 + } + } + + } #[cfg(feature = "const-fn")] // Remove this if there are more tests #[cfg(test)] mod test { - use __core; + use __core::mem::Uninit; use __core::mem::ManuallyDrop; use core; #[cfg(feature = "const-fn")] #[test] - fn static_uninitzialized() { - static mut I: i32 = unsafe { __core::mem::uninitialized() }; - // Initialize before drop - unsafe { core::ptr::write(&mut I as *mut i32, 42) }; - unsafe { assert_eq!(I, 42) }; + fn static_uninit() { + static mut _I: Uninit = unsafe { Uninit::new() }; + unsafe { + *_I = 42; + assert_eq!(*_I, 42); + } } #[cfg(feature = "const-fn")] diff --git a/src/lib.rs b/src/lib.rs index dfa5463bc9..c26d48fc17 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -85,6 +85,7 @@ #![cfg_attr(feature = "const-fn", feature(const_fn))] #![cfg_attr(feature = "const-fn", feature(const_manually_drop_new))] #![cfg_attr(feature = "const-fn", feature(untagged_unions))] +#![cfg_attr(feature = "const-fn", feature(const_fn_union))] #![cfg_attr(feature = "smaller-atomics", feature(core_intrinsics))] #![no_std] diff --git a/src/ring_buffer/mod.rs b/src/ring_buffer/mod.rs index 911ce0a4cc..8c90b7c206 100644 --- a/src/ring_buffer/mod.rs +++ b/src/ring_buffer/mod.rs @@ -7,12 +7,13 @@ use core::ops::Add; use core::ptr; #[cfg(not(feature = "smaller-atomics"))] use core::sync::atomic::{AtomicUsize, Ordering}; +use __core::mem::Uninit; use generic_array::typenum::{Sum, U1, Unsigned}; use generic_array::{ArrayLength, GenericArray}; pub use self::spsc::{Consumer, Producer}; -use __core::mem::{self, ManuallyDrop}; +use __core::mem::{ManuallyDrop}; mod spsc; @@ -230,7 +231,7 @@ where // this is where we enqueue new items tail: Atomic, - buffer: ManuallyDrop>>, + buffer: ManuallyDrop>>>, } impl RingBuffer @@ -334,7 +335,7 @@ macro_rules! impl_ { /// Creates an empty ring buffer with a fixed capacity of `N` pub const fn $uxx() -> Self { RingBuffer { - buffer: ManuallyDrop::new(unsafe { mem::uninitialized() }), + buffer: ManuallyDrop::new(unsafe { Uninit::new() }), head: Atomic::new(0), tail: Atomic::new(0), } diff --git a/src/vec.rs b/src/vec.rs index e7db938dd6..c1e7d9cb2e 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -2,7 +2,7 @@ use core::{fmt, ops, ptr, slice}; use generic_array::{ArrayLength, GenericArray}; -use __core::mem::{self, ManuallyDrop}; +use __core::mem::{ManuallyDrop, Uninit}; use core::iter::FromIterator; @@ -39,7 +39,7 @@ pub struct Vec where N: ArrayLength, { - buffer: ManuallyDrop>, + buffer: ManuallyDrop>>, len: usize, } @@ -52,7 +52,7 @@ where /// Constructs a new, empty vector with a fixed capacity of `N` pub const fn new() -> Self { Vec { - buffer: ManuallyDrop::new(unsafe { mem::uninitialized() }), + buffer: ManuallyDrop::new(unsafe { Uninit::new() }), len: 0, } }