Generic Const Arguments (GCA)
Generic Const Arguments (GCA)
Thesis
On stable Rust, a const generic parameter may appear in a const argument alone ([u8; N]) or as a fully concrete expression ([u8; 1 + 1]). The moment you write [u8; N + 1] or [u8; T::ASSOC], the compiler stops you. The old escape hatch, #![feature(generic_const_exprs)] (GCE), taught everyone the shape of the problem but never became a stabilization candidate.
Generic Const Arguments (GCA) is the Const Generics project group’s replacement family of nightly features. Expressions that involve generic parameters go through an explicit gca!(…) marker (for now), each capability has its own gate (gca_adts, gca_min_const_items, gca_const_items, …), and definitional equality — not GCE’s evaluation model — decides when two const arguments match. Nothing here is stable. This chapter shows what compiles on today’s nightly, marks every feature gate, and records where the Oct 2026 blog post already drifted from the compiler.
Version note: verified on rustc 1.101.0-nightly (a30aa9064 2026-10-08). The Inside Rust post Generic Const Args and You (2026-10-02) is the design overview; on this nightly the feature formerly named generic_const_args has been renamed to gca_const_items (removed name errors say “removed in 1.100.0”), and the gca! macro lives at std::gca / core::gca. No RFC yet; the project group says polish first.
Stable const generics basics (structs/functions parameterized by const N: usize) live in Generic Functions and Data Structures. This chapter does not re-teach that.
Mental model
Stable today
const arg ::= N | <fully concrete expr>
└── generic param alone
GCE (legacy nightly) — evaluate complex exprs; hard to stabilize
GCA (current nightly) — mark exprs with gca!(…); equality by definition
│
├── gca_adts arrays / tuples / structs / enums in gca!(…)
├── gca_min_const_items const items whose RHS is gca!(…)
├── gca_const_items + opaque const items, assoc bindings, dyn, needs -Znext-solver often
└── gca_macroless_* experimental: insert gca!(…) for you (rough)
| Fact | Consequence |
|---|---|
gca!(…) may mention generic parameters |
Plain { N + 1 } as a const argument still cannot |
gca!(…) accepts fewer expression kinds than a normal const block |
gca!(N + 1) and gca!(foo()) are not automatically legal; prefer const items / ADTs that the gates support |
gca_const_items requires gca_min_const_items |
Enable both; incomplete-feature warnings are expected |
Feature generic_const_args is gone on 1.101 nightly |
Use gca_const_items (compiler points the rename) |
| Nothing is stabilization-ready | APIs that expose gca!(…) in public signatures are a SemVer hazard while the syntax is explicit |
Worked examples
All listings were compiled with:
rustup toolchain install nightly --profile minimal # once
rustc +nightly --versionrustc 1.101.0-nightly (a30aa9064 2026-10-08)
Case 0: stable still rejects N + 1
// stable_fail.rs — what stable const generics refuse
fn make<const N: usize>() -> [u8; N + 1] {
[0; N + 1]
}
fn main() {
let _ = make::<3>();
}rustc --edition 2024 stable_fail.rserror: generic parameters may not be used in const operations
--> stable_fail.rs:1:35
|
1 | fn make<const N: usize>() -> [u8; N + 1] {
| ^ cannot perform const operation using `N`
|
= help: const parameters may only be used as standalone arguments here, i.e. `N`
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
= help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item
Note the help text still mentions GCE and GCA — both are nightly escape hatches; new code should reach for GCA, not GCE.
Case 1: ADT const arguments with gca_adts
Build a const-generic parameter whose type is a struct, then construct that struct from another const parameter inside gca!(…):
// gca_adt.rs — struct expressions as const arguments (nightly GCA)
#![feature(gca_adts, adt_const_params, gca_min_const_items)]
#![expect(incomplete_features)]
use std::gca;
use std::marker::ConstParamTy;
#[derive(ConstParamTy, Eq, PartialEq)]
struct TupleStruct(usize);
fn accepts<const N: TupleStruct>() -> usize {
N.0
}
fn example<const N: usize>() -> usize {
accepts::<gca!(TupleStruct(N))>()
}
fn main() {
println!("{}", example::<7>());
}rustc +nightly --edition 2024 gca_adt.rs -o gca_adt && ./gca_adt7
The same pattern works for enum variants, arrays (gca!([N1, 12])), and tuples (gca!((N1, 12))) per the project-group post. Array repeat syntax (gca!([N1; 2])) is still explicitly not supported.
Case 2: Associated constants with gca_const_items
// gca_assoc.rs — associated consts in array lengths (nightly GCA)
#![feature(gca_min_const_items, gca_const_items)]
#![expect(incomplete_features)]
use std::gca;
trait Trait {
const ASSOC: usize;
}
impl Trait for u8 {
const ASSOC: usize = 3;
}
fn example<T: Trait>() -> [u8; gca!(T::ASSOC)] {
[0x1; _]
}
fn main() {
let a = example::<u8>();
println!("len={}", a.len());
}rustc +nightly --edition 2024 gca_assoc.rs -Znext-solver -o gca_assoc && ./gca_assoclen=3
-Znext-solver is required for the full gca_const_items path in current nightlies. Treat that as part of the experiment, not as something to bake into stable CI.
Case 3: Macroless (experimental)
gca_macroless_args asks the compiler to insert gca!(…) for you. It works for some associated-const cases on this nightly, and the project group still recommends writing gca!(…) explicitly:
// gca_macroless.rs — implicit gca!(…) (rough; prefer explicit)
#![feature(gca_min_const_items, gca_const_items, gca_macroless_args)]
#![expect(incomplete_features)]
trait Trait {
const ASSOC: usize;
}
impl Trait for u8 {
const ASSOC: usize = 3;
}
fn make_array<T: Trait>() -> [u8; T::ASSOC] {
[0x1; _]
}
fn main() {
println!("{}", make_array::<u8>().len());
}rustc +nightly --edition 2024 gca_macroless.rs -Znext-solver -o gca_macroless && ./gca_macroless3
Case 4: What still hurts — arithmetic inside gca!
The blog’s long-term story is “put complex ops in const items.” On 1.101 nightly, a direct gca!(N + 1) as a const-item RHS is still rejected:
// gca_arith.rs — not there yet on 2026-10-08 nightly
#![feature(gca_min_const_items, gca_const_items, generic_const_items)]
#![expect(incomplete_features)]
use std::gca;
const INC<const N: usize>: usize = gca!(N + 1);
fn make<const N: usize>() -> [u8; INC::<N>] {
[0; INC::<N>]
}
fn main() {
let _ = make::<3>();
}rustc +nightly --edition 2024 gca_arith.rserror: complex const arguments must be placed inside of a `const` block
--> gca_arith.rs:5:41
|
5 | const INC<const N: usize>: usize = gca!(N + 1);
| ^^^^^
So: ADTs and associated-const uses are the productive surface today; “any arithmetic via gca!” is not. Re-check nightly before teaching a team pattern around arithmetic helpers.
The trap
- Copy-pasting
#![feature(generic_const_args)]from older posts. Removed in 1.100; rename togca_const_itemsand enablegca_min_const_itemswith it. - Assuming
gca!(…)is a full const evaluator. It is a marker for a restricted expression grammar that may mention generics. Unsupported ops fail loudly. - Stabilizing public APIs on
gca!. The macroless work exists precisely because explicitgca!is considered ergonomically temporary — and also SemVer-visible. - Mixing GCE and GCA in one crate “just to make it compile”. Two incomplete models; pick GCA for new experiments.
- Forgetting
#![expect(incomplete_features)]/#[allow(incomplete_features)]. Without it, every build is a warning storm (or worse, depending on lint config).
The boring rule
Stay on stable const generics (N alone, or concrete exprs) for production. When you truly need generic const computation, use current nightly GCA with explicit gca!(…), gate every file with the specific features you touch, pin the nightly date in the chapter/PR, and re-run the listings after each toolchain bump — the rename from generic_const_args to gca_const_items already proved the surface moves.
Try this
- Compile Case 1 and Case 2 on your nightly; paste
rustc +nightly --versionnext to the output. - Attempt one
gca!([N; 2])repeat expression and confirm it still errors; watch the tracking issues for when it lands. - Skim the project-const-generics repo / Zulip before filing duplicates — design feedback is solicited there.
Sources
- Generic Const Args and You — Inside Rust, 2026-10-02 (inspiration; see Updated vs original in the PR)
- generic_const_args — Unstable Book (tracking issue #151972)
- Full Const Generics — 2026 project goal
- Verified locally:
rustc 1.101.0-nightly (a30aa9064 2026-10-08)