Skip to content

Commit 10b4241

Browse files
committed
Boring movement
1 parent 118fd1f commit 10b4241

File tree

3 files changed

+98
-87
lines changed

3 files changed

+98
-87
lines changed

src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
- [Impl trait type](types/impl-trait.md)
9292
- [Type parameters](types/parameters.md)
9393
- [Inferred type](types/inferred.md)
94+
- [Const Generics](const-generics.md)
9495
- [Dynamically Sized Types](dynamically-sized-types.md)
9596
- [Type layout](type-layout.md)
9697
- [Interior mutability](interior-mutability.md)

src/const-generics.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
r[const-generics]
2+
# Const Generics
3+
4+
r[const-generics.argument]
5+
A const argument in a [path] specifies the const value to use for that item.
6+
7+
r[const-generics.argument.type]
8+
The argument must be a [const expression] of the type ascribed to the const
9+
parameter.
10+
11+
r[items.generics.const.type-ambiguity]
12+
When there is ambiguity if a generic argument could be resolved as either a
13+
type or const argument, it is always resolved as a type. Placing the argument
14+
in a block expression can force it to be interpreted as a const argument.
15+
16+
<!-- TODO: Rewrite the paragraph above to be in terms of namespaces, once
17+
namespaces are introduced, and it is clear which namespace each parameter
18+
lives in. -->
19+
20+
```rust,compile_fail
21+
type N = u32;
22+
struct Foo<const N: usize>;
23+
// The following is an error, because `N` is interpreted as the type alias `N`.
24+
fn foo<const N: usize>() -> Foo<N> { todo!() } // ERROR
25+
// Can be fixed by wrapping in braces to force it to be interpreted as the `N`
26+
// const parameter:
27+
fn bar<const N: usize>() -> Foo<{ N }> { todo!() } // ok
28+
```
29+
30+
r[items.generics.const.exhaustiveness]
31+
When resolving a trait bound obligation, the exhaustiveness of all
32+
implementations of const parameters is not considered when determining if the
33+
bound is satisfied. For example, in the following, even though all possible
34+
const values for the `bool` type are implemented, it is still an error that
35+
the trait bound is not satisfied:
36+
37+
```rust,compile_fail
38+
struct Foo<const B: bool>;
39+
trait Bar {}
40+
impl Bar for Foo<true> {}
41+
impl Bar for Foo<false> {}
42+
43+
fn needs_bar(_: impl Bar) {}
44+
fn generic<const B: bool>() {
45+
let v = Foo::<B>;
46+
needs_bar(v); // ERROR: trait bound `Foo<B>: Bar` is not satisfied
47+
}
48+
```
49+
50+
r[items.generics.const.standalone]
51+
As a further restriction, const parameters may only appear as a standalone
52+
argument inside of a [type] or [array repeat expression]. In those contexts,
53+
they may only be used as a single segment [path expression], possibly inside a
54+
[block] (such as `N` or `{N}`). That is, they cannot be combined with other
55+
expressions.
56+
57+
```rust,compile_fail
58+
// Examples where const parameters may not be used.
59+
60+
// Not allowed to combine in other expressions in types, such as the
61+
// arithmetic expression in the return type here.
62+
fn bad_function<const N: usize>() -> [u8; {N + 1}] {
63+
// Similarly not allowed for array repeat expressions.
64+
[1; {N + 1}]
65+
}
66+
```
67+
68+
The const expression must be a [block expression][block]
69+
(surrounded with braces) unless it is a single path segment (an [IDENTIFIER])
70+
or a [literal] (with a possibly leading `-` token).
71+
72+
> [!NOTE]
73+
> This syntactic restriction is necessary to avoid requiring infinite lookahead when parsing an expression inside of a type.
74+
75+
```rust
76+
fn double<const N: i32>() {
77+
println!("doubled: {}", N * 2);
78+
}
79+
80+
const SOME_CONST: i32 = 12;
81+
82+
fn example() {
83+
// Example usage of a const argument.
84+
double::<9>();
85+
double::<-123>();
86+
double::<{7 + 8}>();
87+
double::<SOME_CONST>();
88+
double::<{ SOME_CONST + 5 }>();
89+
}
90+
```
91+
92+
[block]: ../expressions/block-expr.md
93+
[const expression]: ../const_eval.md#constant-expressions
94+
[literal]: ../expressions/literal-expr.md
95+
[path]: ../paths.md

src/items/generics.md

Lines changed: 2 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -124,71 +124,7 @@ fn foo<const N: usize>() {
124124
}
125125
```
126126

127-
r[items.generics.const.standalone]
128-
As a further restriction, const parameters may only appear as a standalone
129-
argument inside of a [type] or [array repeat expression]. In those contexts,
130-
they may only be used as a single segment [path expression], possibly inside a
131-
[block] (such as `N` or `{N}`). That is, they cannot be combined with other
132-
expressions.
133-
134-
```rust,compile_fail
135-
// Examples where const parameters may not be used.
136-
137-
// Not allowed to combine in other expressions in types, such as the
138-
// arithmetic expression in the return type here.
139-
fn bad_function<const N: usize>() -> [u8; {N + 1}] {
140-
// Similarly not allowed for array repeat expressions.
141-
[1; {N + 1}]
142-
}
143-
```
144-
145-
r[items.generics.const.argument]
146-
A const argument in a [path] specifies the const value to use for that item.
147-
148-
r[items.generics.const.argument.const-expr]
149-
The argument must be a [const expression] of the type ascribed to the const
150-
parameter. The const expression must be a [block expression][block]
151-
(surrounded with braces) unless it is a single path segment (an [IDENTIFIER])
152-
or a [literal] (with a possibly leading `-` token).
153-
154-
> [!NOTE]
155-
> This syntactic restriction is necessary to avoid requiring infinite lookahead when parsing an expression inside of a type.
156-
157-
```rust
158-
fn double<const N: i32>() {
159-
println!("doubled: {}", N * 2);
160-
}
161-
162-
const SOME_CONST: i32 = 12;
163-
164-
fn example() {
165-
// Example usage of a const argument.
166-
double::<9>();
167-
double::<-123>();
168-
double::<{7 + 8}>();
169-
double::<SOME_CONST>();
170-
double::<{ SOME_CONST + 5 }>();
171-
}
172-
```
173-
174-
r[items.generics.const.type-ambiguity]
175-
When there is ambiguity if a generic argument could be resolved as either a
176-
type or const argument, it is always resolved as a type. Placing the argument
177-
in a block expression can force it to be interpreted as a const argument.
178-
179-
<!-- TODO: Rewrite the paragraph above to be in terms of namespaces, once
180-
namespaces are introduced, and it is clear which namespace each parameter
181-
lives in. -->
182-
183-
```rust,compile_fail
184-
type N = u32;
185-
struct Foo<const N: usize>;
186-
// The following is an error, because `N` is interpreted as the type alias `N`.
187-
fn foo<const N: usize>() -> Foo<N> { todo!() } // ERROR
188-
// Can be fixed by wrapping in braces to force it to be interpreted as the `N`
189-
// const parameter:
190-
fn bar<const N: usize>() -> Foo<{ N }> { todo!() } // ok
191-
```
127+
There are limitations around how a const parameter can be used within a const argument ([const generics]).
192128

193129
r[items.generics.const.variance]
194130
Unlike type and lifetime parameters, const parameters can be declared without
@@ -207,26 +143,6 @@ struct Unconstrained;
207143
impl<const N: usize> Unconstrained {}
208144
```
209145

210-
r[items.generics.const.exhaustiveness]
211-
When resolving a trait bound obligation, the exhaustiveness of all
212-
implementations of const parameters is not considered when determining if the
213-
bound is satisfied. For example, in the following, even though all possible
214-
const values for the `bool` type are implemented, it is still an error that
215-
the trait bound is not satisfied:
216-
217-
```rust,compile_fail
218-
struct Foo<const B: bool>;
219-
trait Bar {}
220-
impl Bar for Foo<true> {}
221-
impl Bar for Foo<false> {}
222-
223-
fn needs_bar(_: impl Bar) {}
224-
fn generic<const B: bool>() {
225-
let v = Foo::<B>;
226-
needs_bar(v); // ERROR: trait bound `Foo<B>: Bar` is not satisfied
227-
}
228-
```
229-
230146
r[items.generics.where]
231147
## Where clauses
232148

@@ -290,10 +206,10 @@ struct Foo<#[my_flexible_clone(unbounded)] H> {
290206
[associated const]: associated-items.md#associated-constants
291207
[associated type]: associated-items.md#associated-types
292208
[attributes]: ../attributes.md
293-
[block]: ../expressions/block-expr.md
294209
[const contexts]: ../const_eval.md#const-context
295210
[const expression]: ../const_eval.md#constant-expressions
296211
[const item]: constant-items.md
212+
[const generics]: ../const-generics.md
297213
[enumerations]: enumerations.md
298214
[functions]: functions.md
299215
[function pointers]: ../types/function-pointer.md
@@ -303,7 +219,6 @@ struct Foo<#[my_flexible_clone(unbounded)] H> {
303219
[implementations]: implementations.md
304220
[item declarations]: ../statements.md#item-declarations
305221
[item]: ../items.md
306-
[literal]: ../expressions/literal-expr.md
307222
[path]: ../paths.md
308223
[path expression]: ../expressions/path-expr.md
309224
[raw pointers]: ../types/pointer.md#raw-pointers-const-and-mut

0 commit comments

Comments
 (0)