From 2e90deea3d1925e0d4635f3822d48ef442b3508e Mon Sep 17 00:00:00 2001 From: whentze Date: Tue, 14 Aug 2018 23:48:33 +0200 Subject: [PATCH 1/4] Add #![feature(const_fn_union)] when needed This crate currently fails to compile on the newest nightly when using the "const-fn" feature because unions in const fns now require a feature flag. This change adds the feature flag when using that feature. --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) 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] From a7f1b509d0947db309b6c1678b6bcb2fb06b8582 Mon Sep 17 00:00:00 2001 From: Felix Stegmaier Date: Fri, 17 Aug 2018 15:30:59 +0200 Subject: [PATCH 2/4] WIP workaround --- src/__core.rs | 51 ++++++++++++++++++++++++++++++------------ src/ring_buffer/mod.rs | 7 +++--- src/vec.rs | 6 ++--- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/__core.rs b/src/__core.rs index 001a802479..d3b3ca6f10 100644 --- a/src/__core.rs +++ b/src/__core.rs @@ -1,36 +1,59 @@ /// 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}; + use core::ops::{Deref, DerefMut}; + + /// extremely unsafe uniniatilized memory + /// only use with ManuallyDrop + #[allow(unions_with_drop_fields)] #[cfg(feature = "const-fn")] - pub const unsafe fn uninitialized() -> T { - #[allow(unions_with_drop_fields)] - union U { - none: (), - some: T, + pub(crate) union Uninit { + uninit: (), + init: T, + } + + impl Uninit { + const_fn!( + pub const unsafe fn new() -> Self { + Uninit { + uninit: () + } + } + ); + } + + impl Deref for Uninit { + type Target = T; + fn deref(&self) -> &T { + unsafe{ &self.init } } + } - U { none: () }.some + impl DerefMut for Uninit { + fn deref_mut(&mut self) -> &mut T { + unsafe { &mut self.init } + } } + } #[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/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, } } From 5b229e9025aaaf6e60c6b6342bce9a54d6056b17 Mon Sep 17 00:00:00 2001 From: Felix Stegmaier Date: Fri, 17 Aug 2018 15:36:40 +0200 Subject: [PATCH 3/4] always uninit --- src/__core.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/__core.rs b/src/__core.rs index d3b3ca6f10..7351a4c5a0 100644 --- a/src/__core.rs +++ b/src/__core.rs @@ -8,7 +8,6 @@ pub mod mem { /// extremely unsafe uniniatilized memory /// only use with ManuallyDrop #[allow(unions_with_drop_fields)] - #[cfg(feature = "const-fn")] pub(crate) union Uninit { uninit: (), init: T, From 343a8c6a6361de122a0981d2f98fa64c2b7f4d51 Mon Sep 17 00:00:00 2001 From: Felix Stegmaier Date: Fri, 17 Aug 2018 15:46:52 +0200 Subject: [PATCH 4/4] no-default-features friendly uninit --- src/__core.rs | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/__core.rs b/src/__core.rs index 7351a4c5a0..cb32e40532 100644 --- a/src/__core.rs +++ b/src/__core.rs @@ -1,18 +1,20 @@ /// Temporary fork of some stuff in `core` that's doesn't have a `const fn` API pub mod mem { - 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 { @@ -23,6 +25,7 @@ pub mod mem { ); } + #[cfg(feature = "const-fn")] impl Deref for Uninit { type Target = T; fn deref(&self) -> &T { @@ -30,12 +33,41 @@ pub mod mem { } } + #[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