Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix broken nightly: Const fn union workaround #52

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 69 additions & 15 deletions src/__core.rs
Original file line number Diff line number Diff line change
@@ -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<T> {
uninit: (),
init: T,
}

#[cfg(feature = "const-fn")]
impl<T> Uninit<T> {
const_fn!(
pub const unsafe fn new() -> Self {
Uninit {
uninit: ()
}
}
);
}

#[cfg(feature = "const-fn")]
pub const unsafe fn uninitialized<T>() -> T {
#[allow(unions_with_drop_fields)]
union U<T> {
none: (),
some: T,
impl<T> Deref for Uninit<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe{ &self.init }
}
}

U { none: () }.some
#[cfg(feature = "const-fn")]
impl<T> DerefMut for Uninit<T> {
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>(T);

#[cfg(not(feature = "const-fn"))]
impl<T> Uninit<T> {
pub unsafe fn new() -> Self {
Uninit(uninitialized())
}
}

#[cfg(not(feature = "const-fn"))]
impl<T> Deref for Uninit<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}

#[cfg(not(feature = "const-fn"))]
impl<T> DerefMut for Uninit<T> {
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<i32> = unsafe { Uninit::new() };
unsafe {
*_I = 42;
assert_eq!(*_I, 42);
}
}

#[cfg(feature = "const-fn")]
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]

Expand Down
7 changes: 4 additions & 3 deletions src/ring_buffer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -230,7 +231,7 @@ where
// this is where we enqueue new items
tail: Atomic<U>,

buffer: ManuallyDrop<GenericArray<T, Sum<N, U1>>>,
buffer: ManuallyDrop<Uninit<GenericArray<T, Sum<N, U1>>>>,
}

impl<T, N, U> RingBuffer<T, N, U>
Expand Down Expand Up @@ -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),
}
Expand Down
6 changes: 3 additions & 3 deletions src/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -39,7 +39,7 @@ pub struct Vec<T, N>
where
N: ArrayLength<T>,
{
buffer: ManuallyDrop<GenericArray<T, N>>,
buffer: ManuallyDrop<Uninit<GenericArray<T, N>>>,
len: usize,
}

Expand All @@ -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,
}
}
Expand Down