mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-07 09:13:07 +03:00
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:
@@ -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];
|
||||
```
|
||||
Reference in New Issue
Block a user