Skip to content

Commit 3c1ab0c

Browse files
Rollup merge of rust-lang#155543 - popzxc:document-generic-const-features, r=BoxyUwU
docs(unstable-book): Document const generics features Relevant tracking issues: rust-lang#113521 rust-lang#132980 rust-lang#76560 rust-lang#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
2 parents 3a0d85f + c4eb1bf commit 3c1ab0c

5 files changed

Lines changed: 278 additions & 3 deletions

File tree

compiler/rustc_feature/src/unstable.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -563,8 +563,9 @@ declare_features! (
563563
/// Allows defining gen blocks and `gen fn`.
564564
(unstable, gen_blocks, "1.75.0", Some(117078)),
565565
/// Allows using generics in more complex const expressions, based on definitional equality.
566-
(unstable, generic_const_args, "1.95.0", Some(151972)),
567-
/// Allows non-trivial generic constants which have to have wfness manually propagated to callers
566+
(incomplete, generic_const_args, "1.95.0", Some(151972)),
567+
/// Allows non-trivial generic constants which have to be shown to successfully evaluate
568+
/// to a value by being part of an item signature.
568569
(incomplete, generic_const_exprs, "1.56.0", Some(76560)),
569570
/// Allows generic parameters and where-clauses on free & associated const items.
570571
(incomplete, generic_const_items, "1.73.0", Some(113521)),
@@ -626,7 +627,8 @@ declare_features! (
626627
/// Allows additional const parameter types, such as [u8; 10] or user defined types.
627628
/// User defined types must not have fields more private than the type itself.
628629
(unstable, min_adt_const_params, "1.96.0", Some(154042)),
629-
/// Enables the generic const args MVP (only bare paths, not arbitrary computation).
630+
/// Enables the generic const args MVP (paths to type const items and constructors
631+
/// for ADTs and primitives).
630632
(incomplete, min_generic_const_args, "1.84.0", Some(132980)),
631633
/// A minimal, sound subset of specialization intended to be used by the
632634
/// standard library until the soundness issues with specialization
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# generic_const_args
2+
3+
Allows using generics in more complex const expressions, based on definitional equality.
4+
5+
The tracking issue for this feature is: [#151972]
6+
7+
[#151972]: https://github.com/rust-lang/rust/issues/151972
8+
9+
------------------------
10+
11+
Warning: This feature is incomplete; its design and syntax may change.
12+
13+
This feature enables many of the same use cases supported by [generic_const_exprs],
14+
but based on the machinery developed for [min_generic_const_args]. In a way, it is
15+
meant to be an interim successor for GCE (though it might not currently support all
16+
the valid cases that supported by GCE).
17+
18+
See also: [generic_const_items]
19+
20+
[min_generic_const_args]: min-generic-const-args.md
21+
[generic_const_exprs]: generic-const-exprs.md
22+
[generic_const_items]: generic-const-items.md
23+
24+
## Examples
25+
26+
```rust
27+
#![feature(generic_const_items)]
28+
#![feature(min_generic_const_args)]
29+
#![feature(generic_const_args)]
30+
#![expect(incomplete_features)]
31+
32+
type const ADD1<const N: usize>: usize = const { N + 1 };
33+
34+
type const INC<const N: usize>: usize = ADD1::<N>;
35+
36+
const ARR: [(); ADD1::<0>] = [(); INC::<0>];
37+
```
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# generic_const_exprs
2+
3+
Allows non-trivial generic constants which have to be shown to successfully evaluate
4+
to a value by being part of an item signature.
5+
6+
The tracking issue for this feature is: [#76560]
7+
8+
9+
[#76560]: https://github.com/rust-lang/rust/issues/76560
10+
11+
------------------------
12+
13+
Warning: This feature is incomplete; its design and syntax may change.
14+
15+
See also: [min_generic_const_args], [generic_const_args]
16+
17+
[min_generic_const_args]: min-generic-const-args.md
18+
[generic_const_args]: generic-const-args.md
19+
20+
## Examples
21+
22+
```rust
23+
#![allow(incomplete_features)]
24+
#![feature(generic_const_exprs)]
25+
26+
// Use parameters that depend on a generic argument.
27+
struct Foo<const N: usize>
28+
where
29+
[(); N + 1]:,
30+
{
31+
array: [usize; N + 1],
32+
}
33+
34+
// Use generic parameters in const operations.
35+
trait Bar {
36+
const X: usize;
37+
const Y: usize;
38+
}
39+
40+
// Note `B::X * B::Y`.
41+
const fn baz<B: Bar>(x: [usize; B::X], y: [usize; B::Y]) -> [usize; B::X * B::Y] {
42+
let mut out = [0; B::X * B::Y];
43+
let mut i = 0;
44+
while i < B::Y {
45+
let mut j = 0;
46+
while j < B::X {
47+
out[i * B::X + j] = y[i].saturating_mul(x[j]);
48+
j += 1;
49+
}
50+
i += 1;
51+
}
52+
out
53+
}
54+
55+
56+
// Create a new type based on a generic argument.
57+
pub struct Grow<const N: usize> {
58+
arr: [usize; N],
59+
}
60+
61+
impl<const N: usize> Grow<N> {
62+
pub const fn grow(self, val: usize) -> Grow<{ N + 1 }> {
63+
let mut new_arr = [0; { N + 1 }];
64+
let mut idx = 0;
65+
while idx < N {
66+
new_arr[idx] = self.arr[idx];
67+
idx += 1;
68+
}
69+
new_arr[N] = val;
70+
Grow { arr: new_arr }
71+
}
72+
}
73+
```
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# generic_const_items
2+
3+
Allows generic parameters and where-clauses on free & associated const items.
4+
5+
The tracking issue for this feature is: [#113521]
6+
7+
[#113521]: https://github.com/rust-lang/rust/issues/113521
8+
9+
------------------------
10+
11+
Warning: This feature is an [experiment] and lacks an RFC.
12+
There are no guarantees that it will ever be stabilized.
13+
14+
See also: [generic_const_exprs], [min_generic_const_args].
15+
16+
[experiment]: https://lang-team.rust-lang.org/how_to/experiment.html
17+
[generic_const_exprs]: generic-const-exprs.md
18+
[min_generic_const_args]: min-generic-const-args.md
19+
20+
## Examples
21+
22+
### Generic constant values
23+
24+
```rust
25+
#![allow(incomplete_features)]
26+
#![feature(generic_const_items)]
27+
28+
const GENERIC_VAL<const ARG: usize>: usize = ARG + 1;
29+
30+
#[test]
31+
fn generic_const_arg() {
32+
assert_eq!(GENERIC_VAL::<1>, 2);
33+
assert_eq!(GENERIC_VAL::<2>, 3);
34+
}
35+
```
36+
37+
### Conditional constants
38+
39+
```rust
40+
#![allow(incomplete_features)]
41+
#![feature(generic_const_items)]
42+
43+
// `GENERIC_VAL::<0>` will fail to compile
44+
const GENERIC_VAL<const ARG: usize>: usize = if ARG > 0 { ARG + 1 } else { panic!("0 value") };
45+
46+
// Will fail to compile if the `Copy` derive is removed.
47+
const COPY_MARKER<C: Copy>: () = ();
48+
49+
#[derive(Clone, Copy)]
50+
struct Foo;
51+
52+
const FOO_IS_COPY: () = COPY_MARKER::<Foo>;
53+
```
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# min_generic_const_args
2+
3+
Enables the generic const args MVP (paths to type const items and constructors for ADTs and primitives).
4+
5+
The tracking issue for this feature is: [#132980]
6+
7+
[#132980]: https://github.com/rust-lang/rust/issues/132980
8+
9+
------------------------
10+
11+
Warning: This feature is incomplete; its design and syntax may change.
12+
13+
This feature acts as a minimal alternative to [generic_const_exprs] that allows a smaller subset of functionality,
14+
and uses a different approach for implementation. It is intentionally more restrictive, which helps with avoiding edge
15+
cases that make the `generic_const_exprs` hard to implement properly. See [Feature background][feature_background]
16+
for more details.
17+
18+
Related features: [generic_const_args], [generic_const_items].
19+
20+
[feature_background]: https://github.com/rust-lang/project-const-generics/blob/main/documents/min_const_generics_plan.md
21+
[generic_const_exprs]: generic-const-exprs.md
22+
[generic_const_args]: generic-const-args.md
23+
[generic_const_items]: generic-const-items.md
24+
25+
## `type const` syntax
26+
27+
This feature introduces new syntax: `type const`.
28+
Constants marked as `type const` are allowed to be used in type contexts, e.g.:
29+
30+
```compile_fail
31+
#![allow(incomplete_features)]
32+
#![feature(min_generic_const_args)]
33+
34+
type const X: usize = 1;
35+
const Y: usize = 1;
36+
37+
struct Foo {
38+
good_arr: [(); X], // Allowed
39+
bad_arr: [(); Y], // Will not compile, `Y` must be `type const`.
40+
}
41+
```
42+
43+
## Examples
44+
45+
```rust
46+
#![allow(incomplete_features)]
47+
#![feature(min_generic_const_args)]
48+
49+
trait Bar {
50+
type const VAL: usize;
51+
type const VAL2: usize;
52+
}
53+
54+
struct Baz;
55+
56+
impl Bar for Baz {
57+
type const VAL: usize = 2;
58+
type const VAL2: usize = const { Self::VAL * 2 };
59+
}
60+
61+
struct Foo<B: Bar> {
62+
arr1: [usize; B::VAL],
63+
arr2: [usize; B::VAL2],
64+
}
65+
```
66+
67+
Note that with [generic_const_exprs] the same example would look as follows:
68+
69+
```rust
70+
#![allow(incomplete_features)]
71+
#![feature(generic_const_exprs)]
72+
73+
trait Bar {
74+
const VAL: usize;
75+
const VAL2: usize;
76+
}
77+
78+
struct Baz;
79+
80+
impl Bar for Baz {
81+
const VAL: usize = 2;
82+
const VAL2: usize = const { Self::VAL * 2 };
83+
}
84+
85+
struct Foo<B: Bar>
86+
where
87+
[(); B::VAL]:,
88+
[(); B::VAL2]:,
89+
{
90+
arr1: [usize; B::VAL],
91+
arr2: [usize; B::VAL2],
92+
}
93+
```
94+
95+
Use of const functions is allowed:
96+
97+
```rust
98+
#![allow(incomplete_features)]
99+
#![feature(min_generic_const_args)]
100+
101+
const VAL: usize = 1;
102+
103+
const fn inc(val: usize) -> usize {
104+
val + 1
105+
}
106+
107+
type const INC: usize = const { inc(VAL) };
108+
109+
const ARR: [usize; INC] = [0; INC];
110+
```

0 commit comments

Comments
 (0)