Const Parameters
Const parameters (const IDENT: Type) are the formal declarations of compile-time constant arguments in generic parameter lists (<const N: usize>). Stable Rust restricts which types may be used as const parameter types so the compiler can compare two instantiated types for structural equality (Type<A> == Type<B>) without ambiguity.
Allowed Types for const Parameters
In stable Rust, a const generic parameter must have one of the following structural-match primitive types:
| Allowed Type Category | Concrete Types | Example |
|---|---|---|
| Unsigned integers | u8, u16, u32, u64, u128, usize |
struct Buffer<const CAP: usize> |
| Signed integers | i8, i16, i32, i64, i128, isize |
struct FixedPoint<const SCALE: i32> |
| Booleans | bool |
struct Channel<const BOUNDED: bool> |
| Unicode scalar values | char |
struct Delimited<const SEP: char> |
Floating-point types (f32, f64, because NaN != NaN and -0.0 == +0.0 have ambiguous type-equality semantics), string slices (&'static str), and user-defined structs/enums are rejected as const parameter types on stable Rust (E0741):
// ❌ does not compile
struct NamedMetric<const NAME: &'static str> {
value: u64,
}
fn main() {}
error[E0741]: `&'static str` is forbidden as the type of a const generic parameter
--> src/main.rs:2:32
|
2 | struct NamedMetric<const NAME: &'static str> {
| ^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool`, and `char`
Default Values for const Parameters
Like generic type parameters, const parameters on struct, enum, type alias, and trait definitions can declare default values (const N: usize = 64):
#[derive(Debug)]
struct SmallBuffer<T, const INLINE_CAP: usize = 8> {
storage: [Option<T>; INLINE_CAP],
}
impl<T, const INLINE_CAP: usize> SmallBuffer<T, INLINE_CAP> {
fn new() -> Self {
Self {
storage: [const { None }; INLINE_CAP],
}
}
fn capacity(&self) -> usize {
INLINE_CAP
}
}
fn main() {
// Uses default `INLINE_CAP = 8`:
let default_buf: SmallBuffer<u32> = SmallBuffer::new();
// Overrides `INLINE_CAP = 16`:
let custom_buf: SmallBuffer<u32, 16> = SmallBuffer::new();
println!("default capacity: {}", default_buf.capacity());
println!("custom capacity: {}", custom_buf.capacity());
}
default capacity: 8
custom capacity: 16
Passing Expressions as Const Arguments ({ EXPR })
When supplying a const generic argument at an instantiation site:
- Single literals (
16,true,':') and standaloneconst/ parameter identifiers (N,MAX_LEN) can be written directly:Buffer::<u8, 16>,Buffer::<u8, MAX_LEN>. - Compound constant expressions (
2 * 1024,size_of::<u64>(),1 << 4) must be enclosed in curly braces{ ... }:Buffer::<u8, { 2 * 1024 }>:
fn zero_bytes<const BYTES: usize>() -> [u8; BYTES] {
[0_u8; BYTES]
}
fn main() {
const HEADER_LEN: usize = 4;
// Compound expression `{ HEADER_LEN + size_of::<u64>() }` wrapped in `{ ... }`:
let packet = zero_bytes::<{ HEADER_LEN + size_of::<u64>() }>();
println!("packet length: {} bytes", packet.len());
}
packet length: 12 bytes