-
Notifications
You must be signed in to change notification settings - Fork 173
Description
Summary
The #[uninit]
attribute will place static [mut]
variables into an .uninit
section, located in RAM, that won't be initialized before main
.
Motivation
Today, uninitialized (see MaybeUninit
) static
variables will be placed in
.bss
, which means that'll be zeroed before main
. This leads to unnecessary
work as leaving the memory uninitialized was the intended behavior.
Design
The #[uninit]
attribute will have the following syntax.
#[uninit]
static mut FOO: u32 = {};
The initial value of uninit
variables must be the placeholder {}
. This
attribute will expand into:
#[link_section = ".uninit"]
static mut FOO: core::mem::MaybeUninit<u32> = core::mem::MaybeUninit::new();
#[uninit]
composes with #[entry]
and #[exception]
; it can be used on
safe local static mut
variables.
#[entry]
fn main() -> ! {
#[uninit]
static mut KEY: [u32; 8] = {};
// ..
// the name of this MaybeUninit method hasn't been decided but it writes
// a value into the MaybeUninit and then returns a reference to the written
// value
let key: &'static mut [u32; 8] = KEY.insert(/* runtime value */);
// ..
}
Implementation
Before this can be implemented, MaybeUninit
must first land in the core
library. This feature will live behind a "nightly" (Cargo) feature until
MaybeUninit
and its const constructor are stabilized.
Alternative syntax
Option A
#[uninit]
static mut FOO: u32 = ();
Option B
#[uninit]
static mut FOO: u32 = ..;
We can't omit the RHS of static mut
because then the code won't parse and the
compiler will never reach the macro expansion phase.
Drawbacks
This is not a perfect solution.
For example, a heapless
vector contains an uninitialized buffer when it's
constructed using the new
method but it also contains a length field that must
be initialized to zero. Applying #[uninit]
to such data structure means that
the vector will have to be initialized (assign 0 to its length field) at
runtime, which is not ergonomic. Not using #[uninit]
means that the vector
length and its buffer will be zeroed, which is wasteful.
It's not possible to have partial initialization of static
variables so this
is as good as it gets.