Skip to content

Commit adc3beb

Browse files
committed
Allow MapCell's new to be const
Uses a trick stolen from @japaric here: rust-lang/rust#50150 to avoid using `mem::uninitialized`, which isn't currently marked `const`
1 parent ba8e997 commit adc3beb

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

libraries/tock-cells/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Tock Cell types.
22
3-
#![feature(const_fn)]
3+
#![feature(const_fn, untagged_unions)]
44
#![no_std]
55

66
pub mod map_cell;

libraries/tock-cells/src/map_cell.rs

+26-2
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,34 @@ pub struct MapCell<T> {
1616
occupied: Cell<bool>,
1717
}
1818

19+
// This function allows us to mimic `mem::uninitialized` in a way that can be marked `const`.
20+
// Specifically, we just want to allocate some memory the size of some particular `T` and we don't
21+
// care what's there---this happens to not be marked `cost` in the core library right now since
22+
// it's an LLVM intrinsic.
23+
//
24+
// This uses an unsafe union to do basically the same thing: the union will have the size of the
25+
// larger of the two fields (`T`, since `()` is zero-sized). It then initializes the union with the
26+
// `none` variant (of type `()`), but returns the `some` variant (which is of type `T`), thus
27+
// giving us back something of type `T` with some uninitialized memory.
28+
//
29+
// This is of course wildly unsafe, and should be used with the utmost caution---the value returned
30+
// is _not_ valid!
31+
//
32+
// Credit to @japaric: https://github.com/rust-lang/rust/pull/50150
33+
const unsafe fn uninitialized<T>() -> T {
34+
#[allow(unions_with_drop_fields)]
35+
union U<T> {
36+
none: (),
37+
some: T,
38+
}
39+
40+
U { none: () }.some
41+
}
42+
1943
impl<T> MapCell<T> {
20-
pub fn empty() -> MapCell<T> {
44+
pub const fn empty() -> MapCell<T> {
2145
MapCell {
22-
val: unsafe { mem::uninitialized() },
46+
val: unsafe { uninitialized() },
2347
occupied: Cell::new(false),
2448
}
2549
}

0 commit comments

Comments
 (0)