Mutable Static Variables

It is safe to read an immutable static variable:

static HELLO_WORLD: &str = "Hello, world!";

fn main() {
    println!("HELLO_WORLD: {HELLO_WORLD}");
}

However, since data races can occur, it is unsafe to read and write mutable static variables:

static mut COUNTER: u32 = 0;

fn add_to_counter(inc: u32) {
    // SAFETY: There are no other threads which could be accessing `COUNTER`.
    #[allow(static_mut_refs)]
    unsafe {
        COUNTER += inc;
    }
}

fn main() {
    add_to_counter(42);

    // SAFETY: There are no other threads which could be accessing `COUNTER`.
    #[allow(static_mut_refs)]
    unsafe {
        dbg!(COUNTER);
    }
}
This slide should take about 5 minutes.
  • The program here is safe because it is single-threaded. However, the Rust compiler reasons about functions individually so can’t assume that. Try removing the unsafe and see how the compiler explains that it is undefined behavior to access a mutable static from multiple threads.
  • Rust 2024 edition goes further and makes accessing a mutable static by reference an error by default. We work around this in the example with #[allow(static_mut_refs)]. Don’t do this.
  • Using a mutable static is almost always a bad idea, you should use interior mutability instead.
  • There are some cases where it might be necessary in low-level no_std code, such as implementing a heap allocator or working with some C APIs. In this case you should use pointers rather than references.