rust-embedded / rust-embedded/cortex-m

[RFC] `#[uninit]` for truly uninitialized `static` variables

Open
#398 6 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
1k
Forks
202
Avg merge
6d 2h
Merged PRs (30d)
2

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.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No repository files, tests, or entry points are named. Start by checking whether MaybeUninit and its const constructor have landed in core, then resolve the attribute syntax, initialization behavior, and MaybeUninit access method before assessing an implementation behind a nightly Cargo feature.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
embedded-iot
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
24/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.