Skip to main content
Const generics are generic parameters that range over compile-time constant values rather than types or lifetimes. They allow structs, enums, traits, and functions to be parameterized by specific values, enabling the compiler to generate monomorphized implementations bound to those exact constants.

Syntax and Declaration

A const generic parameter is declared using the const keyword, followed by an identifier, a colon, and a concrete type.

Type Restrictions

As of current stable Rust, the types permitted for const generic parameters are strictly limited to a subset of primitives. You cannot use standard library types (like String), custom structs, or floating-point numbers. Permitted types include:
  • Unsigned integers: u8, u16, u32, u64, u128, usize
  • Signed integers: i8, i16, i32, i64, i128, isize
  • char
  • bool

Instantiation and Inference

When instantiating a type or calling a function with a const generic, the value provided must be a constant expression. The compiler can often infer the const value from the context, particularly when working with arrays.

Const Expressions and Disambiguation

When passing a constant expression (rather than a simple literal or a single identifier) as a generic argument, the expression must be enclosed in braces {}. This disambiguates the expression from standard generic syntax, preventing parsing ambiguities with operators like < and >.
Note on Stable Limitations: While you can use constant expressions to instantiate a const generic, performing arithmetic operations on a const generic parameter within a type signature (e.g., fn split<const N: usize>() -> [u8; { N / 2 }]) requires the #![feature(generic_const_exprs)] nightly feature.

Type System Implications

Const generics create strictly distinct types at compile time. Two types with identical type parameters but different const parameters are entirely incompatible in the type system.
Because they are distinct types, they do not share a memory layout or vtable. The compiler monomorphizes a separate copy of the implementation for every unique value of N encountered in the program.

Parameter Ordering

When combining lifetimes, types, and const generics, Rust enforces a specific declaration order to maintain parsing consistency. The standard ordering is:
  1. Lifetimes ('a)
  2. Types (T)
  3. Const generics (const N: usize)
(Note: Recent Rust versions have relaxed ordering restrictions between types and consts, but placing lifetimes first remains mandatory, and the above ordering remains the idiomatic standard).
Tired of Poor Rust Skills? Fix That With Deep Grasping!Learn More