Advanced Generics and Type-Level Programming

Const Evaluation

Const evaluation (CTFE — Compile-Time Function Evaluation) is the compiler phase in which rustc's internal MIR interpreter evaluates constant expressions during compilation and embeds the resulting values directly into the compiled binary or type definitions.

Contexts That Trigger Guaranteed Compile-Time Evaluation

In Rust, an expression is guaranteed to be evaluated at compile time only when it appears in a const context:

Const Context Syntax Example Evaluated At
const item const MAX_CONNECTIONS: usize = 1024 * 4; Compile time (when referenced)
static / static mut item static HEADER: [u8; 4] = [0x89, b'P', b'N', b'G']; Compile time
Array length expression let buf: [u8; 16 * 8]; Compile time
Array repeat initializer ([const { ... }; N]) let slots: [Option<String>; 8] = [const { None }; 8]; Compile time
Enum discriminant value enum Tag { First = 1 << 3 } Compile time
Const generic argument Matrix::<f32, { 2 + 2 }, 4> Compile time
Inline const { ... } block let table = const { build_crc_table() }; Compile time
Pattern const { ... } block match x { const { 10 * 2 } => ... } Compile time

How the Const Evaluator Works (Miri Engine Inside rustc)

During compilation, rustc lowers const contexts to Mid-level Intermediate Representation (MIR) and executes them inside the same abstract-machine interpreter engine that powers Miri:

Source Code (`const TABLE: [u16; 256] = compute_table();`)
       |
       v
  MIR Lowering
       |
       v
  Compile-Time MIR Interpreter (CTFE)
    +-- Executes loops, branches, and `const fn` calls deterministically
    +-- Rejects integer overflow, out-of-bounds indexing, or UB as a COMPILE ERROR
    +-- Serializes final `[u16; 256]` bytes directly into `.rodata` binary section!

Compile-Time Error Detection During Const Evaluation

Unlike runtime execution where integer overflow in --release wraps and out-of-bounds indexing panics at runtime, any arithmetic overflow, division by zero, out-of-bounds array access, or panic!() encountered in a const context fails compilation immediately with error E0080:

// ❌ does not compile
const ITEMS: [u32; 3] = [10, 20, 30];
const OUT_OF_BOUNDS: u32 = ITEMS[5];

fn main() {}
error[E0080]: evaluation of constant value failed
 --> src/main.rs:3:28
  |
3 | const OUT_OF_BOUNDS: u32 = ITEMS[5];
  |                            ^^^^^^^^ index out of bounds: the length is 3 but the index is 5

Generating a Lookup Table at Compile Time

By computing lookup tables in a const item, the binary starts up with the table already precomputed in read-only memory (0 CPU cycles spent at startup):

const fn generate_popcount_table() -> [u8; 256] {
    let mut table = [0_u8; 256];
    let mut i = 0;
    while i < 256 {
        table[i] = (i as u8).count_ones() as u8;
        i += 1;
    }
    table
}

static POPCOUNT_TABLE: [u8; 256] = generate_popcount_table();

fn main() {
    println!("popcount(0b0000_0000) = {}", POPCOUNT_TABLE[0b0000_0000]);
    println!("popcount(0b1010_0101) = {}", POPCOUNT_TABLE[0b1010_0101]);
    println!("popcount(0b1111_1111) = {}", POPCOUNT_TABLE[0b1111_1111]);
}
popcount(0b0000_0000) = 0
popcount(0b1010_0101) = 4
popcount(0b1111_1111) = 8