Constants & Statics

Constants and statics are Rust's two ways to declare fixed, named values — a const is a compile-time value inlined at every use, while a static is a single value with a fixed memory location that lives for the whole program.

Learn Constants & Statics in our free Rust course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free Rust course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

In this lesson you'll learn const vs static , naming conventions, const fn and compile-time evaluation, the lifetime, and how shadowing differs from a constant.

What You'll Learn in This Lesson

1️⃣ const: Compile-Time Constants

A const declares a value fixed at compile time. You must annotate its type, the value must be a constant expression, and the convention is SCREAMING_SNAKE_CASE . The compiler inlines the value wherever you use it, so it behaves like a named literal — and you can declare one at module scope or inside a function.

Constants are perfect for magic numbers, configuration limits, and mathematical values. Naming them gives the number meaning and a single place to change it.

2️⃣ static & const fn

A static also names a fixed value, but unlike const it has a single memory address and the lifetime — it exists for the entire program. A const fn is a function the compiler can run at compile time , so its result can initialize a const .

3️⃣ Shadowing vs const

Shadowing reuses a variable name with a fresh let , creating a brand-new binding that can even change the type. That's quite different from a const , which is one fixed value with one type. Don't confuse shadowing with mut either — shadowing makes a new binding, while mut changes the existing one.

Your turn. Fill in the blanks marked ___ , then run it.

Compose constants and a const fn so the compiler does the arithmetic before your program even runs. Run it with cargo run and check the output.

📋 Quick Reference — Constants & Statics

Practice quiz

What must you always provide when declaring a const?

  • The mut keyword
  • A lifetime
  • An explicit type annotation
  • A trait bound

Answer: An explicit type annotation. A const cannot infer its type, so you must annotate it, e.g. const MAX: u32 = 100;.

What is the conventional naming style for const and static items?

  • SCREAMING_SNAKE_CASE
  • camelCase
  • snake_case
  • PascalCase

Answer: SCREAMING_SNAKE_CASE. Constants and statics conventionally use SCREAMING_SNAKE_CASE.

How does a const differ from a static in memory?

  • A const has a fixed address; a static is inlined
  • Both have one address
  • Both are inlined identically
  • A const is inlined at each use; a static has one fixed memory address

Answer: A const is inlined at each use; a static has one fixed memory address. A const is inlined wherever used; a static lives at a single fixed address for the whole program.

What does the 'static lifetime mean?

  • The value is mutable
  • The value lives for the entire duration of the program
  • The value is on the stack
  • The value is dropped immediately

Answer: The value lives for the entire duration of the program. 'static means the data lives for the whole program, so references to it are valid forever.

What is a const fn?

  • A function the compiler can evaluate at compile time
  • A function that cannot be called at runtime
  • A constant that acts like a function
  • A function returning only constants

Answer: A function the compiler can evaluate at compile time. A const fn can run at compile time (and still at runtime), so it can initialize a const.

What does this print? const fn square(n: u32) -> u32 { n * n } const NINE: u32 = square(3); fn main() { println!("{}", NINE); }

  • 3
  • 6
  • 9
  • It does not compile

Answer: 9. square(3) is evaluated at compile time to 9 and stored in NINE.

What does this print? const fn seconds_in_hours(h: u32) -> u32 { h * 60 * 60 } const DAY: u32 = seconds_in_hours(24); fn main() { println!("{}", DAY); }

  • 1440
  • 86400
  • 3600
  • 24

Answer: 86400. 24 * 60 * 60 = 86400 seconds in a day, computed at compile time.

What is shadowing?

  • Mutating a variable in place
  • Hiding a const
  • Declaring a static
  • Reusing a name with let to create a brand-new binding, possibly a new type

Answer: Reusing a name with let to create a brand-new binding, possibly a new type. Shadowing makes a new binding with let that hides the old one and can change type.

What does this print? let value = "42"; let value: i32 = value.parse().unwrap(); println!("{}", value + 10);

  • 4210
  • 52
  • 42
  • It does not compile

Answer: 52. Shadowing turns the &str into i32 42, and 42 + 10 is 52.

Why is a static mut considered unsafe to access?

  • It is too slow
  • It cannot be typed
  • Shared mutable global state is not thread-safe
  • It has no address

Answer: Shared mutable global state is not thread-safe. Accessing static mut requires unsafe because shared mutable globals invite data races; prefer Mutex or atomics.