Rust Constants

Constants declared with `const` are always immutable, must have an explicit type, and can be evaluated entirely at compile time.

Declaring a Constant

The `const` keyword creates a value that is bound to a name for the entire program, or for the scope it's declared in. Unlike `let`, a type annotation is mandatory -- the compiler will not infer it for you.

Basic Constant

const MAX_ATTEMPTS: u32 = 5;

fn main() {
    println!("You have {} attempts remaining", MAX_ATTEMPTS);
}

const vs let: Three Key Differences

`const` and an immutable `let` binding look similar on the surface, but they behave quite differently under the hood.

  • `const` can never be made mutable -- there's no `const mut`, ever
  • `const` requires an explicit type annotation; `let` usually doesn't
  • `const` values must be computable at compile time -- no calling a function that reads input or does I/O
  • `const` can be declared in any scope, including at module or global level, outside of any function

Naming Convention: SCREAMING_SNAKE_CASE

By strong convention, constants are named in all-uppercase with underscores between words, such as `MAX_ATTEMPTS` or `SECONDS_IN_A_DAY`. This makes them instantly recognizable in code, distinct from ordinary variables and function names.

Global Constants Used Across Functions

const SECONDS_IN_A_DAY: u32 = 24 * 60 * 60;

fn hours_to_seconds(hours: u32) -> u32 {
    hours * 3600
}

fn main() {
    println!("A day has {} seconds", SECONDS_IN_A_DAY);
    println!("6 hours is {} seconds", hours_to_seconds(6));
}

Compile-Time Evaluation

Because `const` expressions are resolved during compilation, the compiler can freely inline them wherever they're used -- there's no runtime lookup or memory address involved the way there might be with a variable. This makes constants effectively free to use, no matter how often they appear.

Constant Expressions

const GRID_WIDTH: usize = 8;
const GRID_HEIGHT: usize = 8;
const CELL_COUNT: usize = GRID_WIDTH * GRID_HEIGHT;

fn main() {
    println!("The grid has {} cells", CELL_COUNT);
}
constlet (immutable)
Type annotationRequiredOptional (inferred)
Can be mutNeverYes, with mut
ScopeAny, including globalFunction/block only
Value known atCompile timeCompile or run time
Note: Reach for `const` for values that are truly fixed for the life of the program -- array sizes, physical constants, configuration ceilings -- not just values you happen not to reassign right now.
Note: You can shadow a `const` name with a `let` inside a function, but it's confusing to readers. Give constants and variables genuinely distinct names instead.

Exercise: Rust Constants

Which keyword declares a constant in Rust?