Rollup merge of #155543 - popzxc:document-generic-const-features, r=BoxyUwU

docs(unstable-book): Document const generics features

Relevant tracking issues: rust-lang/rust#113521 rust-lang/rust#132980 rust-lang/rust#76560 rust-lang/rust#151972

## What

Adds a high-level overview of 4 unstable features related to const generic exprs.

## Why

While trying to learn about the current state of const generic exprs, I found it a bit too hard due to lack of documentation -- had to read through a bunch of tracking issues & look for PRs/examples in the repo just to understand what the feature is about.

Moreover, given that there is a bunch of features with similarly-looking names, it was even more confusing. For that purpose, I also added cross-referencing across (directly or logically) related features.

As a result, I decided to add some more context to the unstable book, so that new readers have an easier time than I had.

## Caveats

I understand that the features are incomplete/experimental, so the docs are at risk of becoming stale, but the book entrypoint already has [a corresponding warning](https://doc.rust-lang.org/unstable-book/), so I guess it should be fine.

Also, given that I did research myself, the examples provided might be not the best to showcase the feature -- happy to provide better examples, if you have suggestions. The examples provided are what "made the feature make sense" to me as an outsider, so there is a chance that they will be good for other external readers too, though.

LLM use disclosue: an LLM was used for self-review only; research, coming up with examples, and writing is mine. Issues reported by LLM were fixed manually too.

r? @BoxyUwU
This commit is contained in:
Guillaume Gomez
2026-05-05 02:50:07 +02:00
committed by GitHub
5 changed files with 278 additions and 3 deletions
+5 -3
View File
@@ -563,8 +563,9 @@ pub fn internal(&self, feature: Symbol) -> bool {
/// Allows defining gen blocks and `gen fn`.
(unstable, gen_blocks, "1.75.0", Some(117078)),
/// Allows using generics in more complex const expressions, based on definitional equality.
(unstable, generic_const_args, "1.95.0", Some(151972)),
/// Allows non-trivial generic constants which have to have wfness manually propagated to callers
(incomplete, generic_const_args, "1.95.0", Some(151972)),
/// Allows non-trivial generic constants which have to be shown to successfully evaluate
/// to a value by being part of an item signature.
(incomplete, generic_const_exprs, "1.56.0", Some(76560)),
/// Allows generic parameters and where-clauses on free & associated const items.
(incomplete, generic_const_items, "1.73.0", Some(113521)),
@@ -626,7 +627,8 @@ pub fn internal(&self, feature: Symbol) -> bool {
/// Allows additional const parameter types, such as [u8; 10] or user defined types.
/// User defined types must not have fields more private than the type itself.
(unstable, min_adt_const_params, "1.96.0", Some(154042)),
/// Enables the generic const args MVP (only bare paths, not arbitrary computation).
/// Enables the generic const args MVP (paths to type const items and constructors
/// for ADTs and primitives).
(incomplete, min_generic_const_args, "1.84.0", Some(132980)),
/// A minimal, sound subset of specialization intended to be used by the
/// standard library until the soundness issues with specialization
@@ -0,0 +1,37 @@
# generic_const_args
Allows using generics in more complex const expressions, based on definitional equality.
The tracking issue for this feature is: [#151972]
[#151972]: https://github.com/rust-lang/rust/issues/151972
------------------------
Warning: This feature is incomplete; its design and syntax may change.
This feature enables many of the same use cases supported by [generic_const_exprs],
but based on the machinery developed for [min_generic_const_args]. In a way, it is
meant to be an interim successor for GCE (though it might not currently support all
the valid cases that supported by GCE).
See also: [generic_const_items]
[min_generic_const_args]: min-generic-const-args.md
[generic_const_exprs]: generic-const-exprs.md
[generic_const_items]: generic-const-items.md
## Examples
```rust
#![feature(generic_const_items)]
#![feature(min_generic_const_args)]
#![feature(generic_const_args)]
#![expect(incomplete_features)]
type const ADD1<const N: usize>: usize = const { N + 1 };
type const INC<const N: usize>: usize = ADD1::<N>;
const ARR: [(); ADD1::<0>] = [(); INC::<0>];
```
@@ -0,0 +1,73 @@
# generic_const_exprs
Allows non-trivial generic constants which have to be shown to successfully evaluate
to a value by being part of an item signature.
The tracking issue for this feature is: [#76560]
[#76560]: https://github.com/rust-lang/rust/issues/76560
------------------------
Warning: This feature is incomplete; its design and syntax may change.
See also: [min_generic_const_args], [generic_const_args]
[min_generic_const_args]: min-generic-const-args.md
[generic_const_args]: generic-const-args.md
## Examples
```rust
#![allow(incomplete_features)]
#![feature(generic_const_exprs)]
// Use parameters that depend on a generic argument.
struct Foo<const N: usize>
where
[(); N + 1]:,
{
array: [usize; N + 1],
}
// Use generic parameters in const operations.
trait Bar {
const X: usize;
const Y: usize;
}
// Note `B::X * B::Y`.
const fn baz<B: Bar>(x: [usize; B::X], y: [usize; B::Y]) -> [usize; B::X * B::Y] {
let mut out = [0; B::X * B::Y];
let mut i = 0;
while i < B::Y {
let mut j = 0;
while j < B::X {
out[i * B::X + j] = y[i].saturating_mul(x[j]);
j += 1;
}
i += 1;
}
out
}
// Create a new type based on a generic argument.
pub struct Grow<const N: usize> {
arr: [usize; N],
}
impl<const N: usize> Grow<N> {
pub const fn grow(self, val: usize) -> Grow<{ N + 1 }> {
let mut new_arr = [0; { N + 1 }];
let mut idx = 0;
while idx < N {
new_arr[idx] = self.arr[idx];
idx += 1;
}
new_arr[N] = val;
Grow { arr: new_arr }
}
}
```
@@ -0,0 +1,53 @@
# generic_const_items
Allows generic parameters and where-clauses on free & associated const items.
The tracking issue for this feature is: [#113521]
[#113521]: https://github.com/rust-lang/rust/issues/113521
------------------------
Warning: This feature is an [experiment] and lacks an RFC.
There are no guarantees that it will ever be stabilized.
See also: [generic_const_exprs], [min_generic_const_args].
[experiment]: https://lang-team.rust-lang.org/how_to/experiment.html
[generic_const_exprs]: generic-const-exprs.md
[min_generic_const_args]: min-generic-const-args.md
## Examples
### Generic constant values
```rust
#![allow(incomplete_features)]
#![feature(generic_const_items)]
const GENERIC_VAL<const ARG: usize>: usize = ARG + 1;
#[test]
fn generic_const_arg() {
assert_eq!(GENERIC_VAL::<1>, 2);
assert_eq!(GENERIC_VAL::<2>, 3);
}
```
### Conditional constants
```rust
#![allow(incomplete_features)]
#![feature(generic_const_items)]
// `GENERIC_VAL::<0>` will fail to compile
const GENERIC_VAL<const ARG: usize>: usize = if ARG > 0 { ARG + 1 } else { panic!("0 value") };
// Will fail to compile if the `Copy` derive is removed.
const COPY_MARKER<C: Copy>: () = ();
#[derive(Clone, Copy)]
struct Foo;
const FOO_IS_COPY: () = COPY_MARKER::<Foo>;
```
@@ -0,0 +1,110 @@
# min_generic_const_args
Enables the generic const args MVP (paths to type const items and constructors for ADTs and primitives).
The tracking issue for this feature is: [#132980]
[#132980]: https://github.com/rust-lang/rust/issues/132980
------------------------
Warning: This feature is incomplete; its design and syntax may change.
This feature acts as a minimal alternative to [generic_const_exprs] that allows a smaller subset of functionality,
and uses a different approach for implementation. It is intentionally more restrictive, which helps with avoiding edge
cases that make the `generic_const_exprs` hard to implement properly. See [Feature background][feature_background]
for more details.
Related features: [generic_const_args], [generic_const_items].
[feature_background]: https://github.com/rust-lang/project-const-generics/blob/main/documents/min_const_generics_plan.md
[generic_const_exprs]: generic-const-exprs.md
[generic_const_args]: generic-const-args.md
[generic_const_items]: generic-const-items.md
## `type const` syntax
This feature introduces new syntax: `type const`.
Constants marked as `type const` are allowed to be used in type contexts, e.g.:
```compile_fail
#![allow(incomplete_features)]
#![feature(min_generic_const_args)]
type const X: usize = 1;
const Y: usize = 1;
struct Foo {
good_arr: [(); X], // Allowed
bad_arr: [(); Y], // Will not compile, `Y` must be `type const`.
}
```
## Examples
```rust
#![allow(incomplete_features)]
#![feature(min_generic_const_args)]
trait Bar {
type const VAL: usize;
type const VAL2: usize;
}
struct Baz;
impl Bar for Baz {
type const VAL: usize = 2;
type const VAL2: usize = const { Self::VAL * 2 };
}
struct Foo<B: Bar> {
arr1: [usize; B::VAL],
arr2: [usize; B::VAL2],
}
```
Note that with [generic_const_exprs] the same example would look as follows:
```rust
#![allow(incomplete_features)]
#![feature(generic_const_exprs)]
trait Bar {
const VAL: usize;
const VAL2: usize;
}
struct Baz;
impl Bar for Baz {
const VAL: usize = 2;
const VAL2: usize = const { Self::VAL * 2 };
}
struct Foo<B: Bar>
where
[(); B::VAL]:,
[(); B::VAL2]:,
{
arr1: [usize; B::VAL],
arr2: [usize; B::VAL2],
}
```
Use of const functions is allowed:
```rust
#![allow(incomplete_features)]
#![feature(min_generic_const_args)]
const VAL: usize = 1;
const fn inc(val: usize) -> usize {
val + 1
}
type const INC: usize = const { inc(VAL) };
const ARR: [usize; INC] = [0; INC];
```