const Blocks
An inline const block—written const { ... } (stabilized in Rust 1.79)—is an expression that forces the compiler to evaluate its body at compile time (or monomorphization time when referencing generic parameters), without requiring you to declare a separate named const item outside the function.
Three Core Uses of Inline const { ... } Blocks
1. Initializing Arrays of Non-Copy Types ([const { None }; N])
In Rust, the array repeat expression [expr; N] normally requires expr to implement Copy unless expr is a const item or an inline const { ... } block! With const { None } or const { Vec::new() }, you can initialize large arrays of non-Copy types (Option<String>, Vec<T>, Mutex<T>, MaybeUninit<T>) inline without declaring a helper const:
use std::sync::Mutex;
fn main() {
// `Option<String>` and `Mutex<Vec<u8>>` do NOT implement `Copy`,
// yet `[const { ... }; N]` initializes the array at compile time!
let slots: [Option<String>; 4] = [const { None }; 4];
let shards: [Mutex<Vec<u8>>; 2] = [const { Mutex::new(Vec::new()) }; 2];
shards[0].lock().unwrap().push(42);
println!("slots: {:?}", slots);
println!("shard[0]: {:?}", *shards[0].lock().unwrap());
}
slots: [None, None, None, None]
shard[0]: [42]
2. Compile-Time Assertions Depending on Generic Parameters
Inside a generic function fn process<T, const N: usize>(), an inline const { assert!(...); } block is evaluated at monomorphization time for each concrete (T, N) instantiation, turning violated layout or size constraints into compile-time errors instead of runtime panics:
fn encode_fixed_chunk<T: Copy, const COUNT: usize>(items: &[T; COUNT]) -> usize {
// Evaluated at compile time when `encode_fixed_chunk` is monomorphized:
const {
assert!(COUNT > 0, "COUNT must be non-zero");
assert!(
size_of::<T>() <= 8,
"Element type T must be at most 8 bytes wide"
);
}
items.len() * size_of::<T>()
}
fn main() {
let data = [10_u32, 20, 30, 40];
println!("encoded byte length: {}", encode_fixed_chunk(&data));
}
encoded byte length: 16
3. Inline const { ... } Patterns in match Expressions
Stabilized in Rust 1.79 alongside inline const expressions, const { ... } blocks can also be used inside match and if let patterns to match against computed compile-time constants without defining named const items:
const fn page_size(shift: u32) -> usize {
1 << shift
}
fn classify_allocation(bytes: usize) -> &'static str {
match bytes {
0 => "empty",
1..=const { page_size(12) } => "fits in 4 KiB page",
const { page_size(12) + 1 }..=const { page_size(21) } => "fits in 2 MiB hugepage",
_ => "oversized allocation",
}
}
fn main() {
println!("512 B: {}", classify_allocation(512));
println!("65,536 B: {}", classify_allocation(65_536));
println!("16 MiB: {}", classify_allocation(16 * 1024 * 1024));
}
512 B: fits in 4 KiB page
65,536 B: fits in 2 MiB hugepage
16 MiB: oversized allocation