Skip to content

Commit

Permalink
Allow MapCell's new to be const
Browse files Browse the repository at this point in the history
Uses a trick stolen from @japaric here:
rust-lang/rust#50150 to avoid using
`mem::uninitialized`, which isn't currently marked `const`
  • Loading branch information
alevy committed Jul 25, 2018
1 parent ba8e997 commit adc3beb
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 3 deletions.
2 changes: 1 addition & 1 deletion libraries/tock-cells/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Tock Cell types.
#![feature(const_fn)]
#![feature(const_fn, untagged_unions)]
#![no_std]

pub mod map_cell;
Expand Down
28 changes: 26 additions & 2 deletions libraries/tock-cells/src/map_cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,34 @@ pub struct MapCell<T> {
occupied: Cell<bool>,
}

// This function allows us to mimic `mem::uninitialized` in a way that can be marked `const`.
// Specifically, we just want to allocate some memory the size of some particular `T` and we don't
// care what's there---this happens to not be marked `cost` in the core library right now since
// it's an LLVM intrinsic.
//
// This uses an unsafe union to do basically the same thing: the union will have the size of the
// larger of the two fields (`T`, since `()` is zero-sized). It then initializes the union with the
// `none` variant (of type `()`), but returns the `some` variant (which is of type `T`), thus
// giving us back something of type `T` with some uninitialized memory.
//
// This is of course wildly unsafe, and should be used with the utmost caution---the value returned
// is _not_ valid!
//
// Credit to @japaric: https://github.com/rust-lang/rust/pull/50150
const unsafe fn uninitialized<T>() -> T {
#[allow(unions_with_drop_fields)]
union U<T> {
none: (),
some: T,
}

U { none: () }.some
}

impl<T> MapCell<T> {
pub fn empty() -> MapCell<T> {
pub const fn empty() -> MapCell<T> {
MapCell {
val: unsafe { mem::uninitialized() },
val: unsafe { uninitialized() },
occupied: Cell::new(false),
}
}
Expand Down

0 comments on commit adc3beb

Please sign in to comment.