What is the difference between a constant and a static variable and which should I choose?

Mutability

A constant in Rust is immutable. You neither can reassign nor modify it:

struct Foo(u32);

const FOO: Foo = Foo(5);
const mut FOO: Foo = Foo(5); // illegal

fn main() {
    FOO = Foo(1); //illegal
    FOO.0 = 2; //illegal
}

A static variable can be mutable and therefore can either be modified or reassigned. Note that writing/modifying a global static variable is unsafe and therefore needs an unsafe block:

struct Foo(u32);
static FOO: Foo = Foo(5);
static mut FOO_MUT: Foo = Foo(3);

fn main() {
    unsafe {
        FOO = Foo(1); //illegal
        FOO.0 = 2; //illegal

        FOO_MUT = Foo(1);
        FOO_MUT.0 = 2;
    }
}

Occurrences

When you compile a binary, all const “occurrences” (where you use that const in your source code) will be replaced by that value directly.

statics will have a dedicated section in your binary where they will be placed (the BSS section, see Where are static variables stored in C and C++? for further information).


All in all, stick to a const whenever possible. When not possible, because you need to initialize a variable later in the program of with non-const methods, use lazy_static!.

Interior mutability

While both const and static can use interior mutability you should never ever do it with a const. Here’s an example

use std::sync::atomic::{AtomicU32, Ordering};

static STATIC: AtomicU32 = AtomicU32::new(0);
const CONST: AtomicU32 = AtomicU32::new(0);

fn print() {
    println!("static: {}", STATIC.load(Ordering::Relaxed));
    println!("const:  {}", CONST.load(Ordering::Relaxed));
}

fn main() {
    STATIC.store(3, Ordering::Relaxed);
    CONST.store(3, Ordering::Relaxed);

    print();
}

This compiles fine without any warnings, but leads to unwanted behavoir. Output:

static: 3
const:  0

When using clippy, it will show the two following warnings:

warning: a `const` item should never be interior mutable
 --> src/main.rs:4:1
  |
4 | const CONST: AtomicU32 = AtomicU32::new(0);
  | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  | |
  | make this a static item (maybe with lazy_static)
  |
  = note: `#[warn(clippy::declare_interior_mutable_const)]` on by default
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#declare_interior_mutable_const

warning: a `const` item with interior mutability should not be borrowed
 --> src/main.rs:8:27
  |
8 |     println!("const: {}", CONST.load(Ordering::Relaxed));
  |                           ^^^^^
  |
  = note: `#[warn(clippy::borrow_interior_mutable_const)]` on by default
  = help: assign this const to a local or static variable, and use the variable here
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const

warning: a `const` item with interior mutability should not be borrowed
  --> src/main.rs:13:5
   |
13 |     CONST.store(3, Ordering::Relaxed);
   |     ^^^^^
   |
   = help: assign this const to a local or static variable, and use the variable here
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const

Leave a Comment