🎓 A1Learner
🔍

Rust Const Functions

A const fn is a function that the compiler can run during compilation. Its result can fill values that must exist before the program runs.

Mark a function const

Write const before fn. When a constant needs the answer, the compiler runs the function itself, during compilation. Here AREA becomes 81 before the program ever runs.

const fn square(x: u32) -> u32 {
    x * x
}

const AREA: u32 = square(9);

Loops and if work inside

A const fn body may use loops, if and match — plain logic with no run-time needs. This one adds 1 + 2 + 3 + 4 + 5 and gives 15.

const fn sum_to(n: u32) -> u32 {
    let mut total = 0;
    let mut i = 1;
    while i <= n { total += i; i += 1; }
    total
}

Where const answers are required

An array length must be known at compile time, so it may come from calling a const fn.

const BUF_LEN: usize = square(2) as usize;

fn main() {
    let buffer = [0u8; BUF_LEN];
    println!("buffer holds {} bytes", buffer.len());
}

The same function runs at run time too

Nothing about const fn locks it to compile time. Call it with a value that only exists while running, and it behaves like any other function.

fn main() {
    println!("square(7) = {}", square(7));
}

Example

const fn square(x: u32) -> u32 {
    x * x
}

const fn sum_to(n: u32) -> u32 {
    let mut total = 0;
    let mut i = 1;
    while i <= n {
        total += i;
        i += 1;
    }
    total
}

const fn classify(n: i32) -> char {
    if n < 0 {
        'N'
    } else if n == 0 {
        'Z'
    } else {
        'P'
    }
}

const AREA: u32 = square(9);
const TOTAL: u32 = sum_to(5);
const BUF_LEN: usize = square(2) as usize;

fn main() {
    let buffer = [0u8; BUF_LEN];
    println!("area = {AREA}");
    println!("total 1..=5 = {TOTAL}");
    println!("buffer holds {} bytes", buffer.len());
    println!("classify(-3) = {}", classify(-3));
    println!("square(7) at run time = {}", square(7));
}

Key points

  • A const context is anywhere the answer must exist before the program runs.
  • A const value is one.
  • A static value, an array length and an enum discriminant are others
  • Only compile-time-friendly steps are allowed inside a const fn.
  • No reading files.
  • No printing.
  • No values that only exist while the program runs
  • Even float maths is allowed in a const fn on current Rust

In this example, three small const functions do all the work. square multiplies a number by itself. sum_to uses a while loop to add the numbers from 1 up to n. classify uses if and else if to hand back a letter: N for negative, Z for zero, P for positive. The three const values at the bottom are settled by the compiler itself. AREA is square(9), which is 81. TOTAL is sum_to(5), which is 15. BUF_LEN becomes the length of the buffer array, so the array is built with exactly 4 slots. Inside main, everything is already known except the last two lines. classify(-3) and square(7) are called while the program runs. They work just like ordinary functions. One definition, two moments where it can run.

Note

A normal fn can never be called in a const context.

Marking a function const costs nothing — the very same function still runs normally with values known only at run time.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

When does a const fn actually run at compile time?