Skip to content

Rust - Constant

A constant is a value that is bound to a name and is not allowed to change. In Rust, constants are declared using the const keyword and their type must always be annotated.

const MAX_POINTS: u32 = 100_000;

The naming convention for constants is to use all uppercase letters with underscores between words (SCREAMING_SNAKE_CASE). Constants can be declared in any scope, including the global scope, making them useful for values that are shared across many parts of a program.

const SECONDS_IN_MINUTE: u32 = 60;
const MINUTES_IN_HOUR: u32 = 60;
const SECONDS_IN_HOUR: u32 = SECONDS_IN_MINUTE * MINUTES_IN_HOUR;
fn main() {
println!("There are {} seconds in an hour.", SECONDS_IN_HOUR);
}
There are 3600 seconds in an hour.

Differences Between const and Immutable let

Section titled “Differences Between const and Immutable let”

You might wonder why we need constants when Rust has immutable variables by default (let). While they seem similar, there are important differences:

  • Type Annotation: You must annotate the type of a const. With let, type annotation is usually optional as the compiler can infer it.
  • Mutability: const values can never be made mutable with mut. While let bindings are immutable by default, they can be marked with mut.
  • Evaluation Time: A const must be set to a constant expression, a value that the compiler can determine at compile time. It cannot be the result of a function call or any value computed at runtime.
  • Inlining: const values are effectively inlined into the code wherever they are used. This means there is no single memory address for a const.
  • Scope: const can be declared in any scope, including globally. let is limited to function or block scope.
fn get_runtime_value() -> u32 {
// Some complex calculation...
5
}
fn main() {
// This is valid: The value is computed at compile time.
const COMPILE_TIME_VALUE: u32 = 5 * 2;
// This is NOT valid: The value is computed at runtime.
// const RUNTIME_VALUE: u32 = get_runtime_value(); // Error: calls in constants are limited to constant functions
// An immutable variable is fine for runtime values.
let runtime_variable = get_runtime_value();
println!("Compile-time: {}, Runtime: {}", COMPILE_TIME_VALUE, runtime_variable);
}

Rust has another way to create a value that lives for the entire duration of the program: a static variable. Unlike const, a static variable has a fixed memory location. static variables can also be mutable (using static mut), but accessing or modifying a mutable static variable is unsafe because it can introduce data races. For values that never change, const is almost always the better choice.

static HELLO_WORLD: &str = "Hello, world!";
fn main() {
println!("Static says: {}", HELLO_WORLD);
}

Unlike variables declared with let, constants cannot be shadowed. Attempting to declare another constant with the same name in the same scope will result in a compile-time error.

fn main() {
const NAME: &str = "Alice";
// The following line will cause a compiler error:
// const NAME: usize = 0; // error[E0260]: the name `NAME` is defined multiple times
println!("Name is {}", NAME);
}