Skip to content

Commit 2ebba26

Browse files
committed
Improve the generic_arg_infer docs
Syntactically, the inferred const is either an expression or an `InferredType`, depending on the context. Semantically, though, it's a new kind of const generic argument. Let's add the necessary language and examples in various places to make this all as clear as possible.
1 parent 74723e0 commit 2ebba26

File tree

3 files changed

+35
-8
lines changed

3 files changed

+35
-8
lines changed

src/expressions/array-expr.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ r[expr.array.length-operand]
3535
The expression after the `;` is called the *length operand*.
3636

3737
r[expr.array.length-restriction]
38-
It must have type `usize` and be a [constant expression], such as a [literal] or a [constant item].
38+
The length operand must either be an [inferred const] or be a [constant expression] of type `usize` (e.g. a [literal] or a [constant item]).
3939

4040
r[expr.array.repeat-behavior]
4141
An array expression of this form creates an array with the length of the value of the length operand with each element being a copy of the repeat operand.
@@ -113,6 +113,7 @@ The array index expression can be implemented for types other than arrays and sl
113113
[array]: ../types/array.md
114114
[constant expression]: ../const_eval.md#constant-expressions
115115
[constant item]: ../items/constant-items.md
116+
[inferred const]: items.generics.const.inferred
116117
[literal]: ../tokens.md#literals
117118
[memory location]: ../expressions.md#place-expressions-and-value-expressions
118119
[panic]: ../panic.md

src/items/generics.md

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -172,17 +172,24 @@ fn example() {
172172
```
173173

174174
r[items.generics.const.inferred]
175-
Where a const argument is expected, an `_` (optionally surrounding by any number of matching parentheses), called the "inferred const", can be used instead. This asks the compiler to infer the const argument if possible based on surrounding information.
175+
Where a const argument is expected, an `_` (optionally surrounding by any number of matching parentheses), called the *inferred const* ([path rules][paths.expr.complex-const-params]), can be used instead. This asks the compiler to infer the const argument if possible based on surrounding information.
176176

177177
```rust
178-
fn make_buf() -> [u8; 1024] {
179-
[0x1; _]
180-
// ^ Infers `1024`.
178+
fn make_buf<const N: usize>() -> [u8; N] {
179+
[0; _]
180+
// ^ Infers `N`.
181181
}
182+
let _: [u8; 1024] = make_buf::<_>();
183+
// ^ Infers `1024`.
182184
```
183185

184186
r[items.generics.const.inferred.constraint]
185-
It cannot be used in item signatures.
187+
The inferred const cannot be used in item signatures.
188+
189+
```rust,compile_fail
190+
fn f<const N: usize>(x: [u8; N]) -> [u8; _] { x }
191+
// ^ ERROR
192+
```
186193

187194
r[items.generics.const.type-ambiguity]
188195
When there is ambiguity if a generic argument could be resolved as either a

src/paths.md

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,24 @@ The order of generic arguments is restricted to lifetime arguments, then type
9191
arguments, then const arguments, then equality constraints.
9292

9393
r[paths.expr.complex-const-params]
94-
Const arguments must be surrounded by braces unless they are a
95-
[literal] or a single segment path.
94+
Const arguments must be surrounded by braces unless they are a [literal], an [inferred const], or a single segment path.
95+
96+
```rust
97+
mod m {
98+
pub const C: usize = 42;
99+
}
100+
const C: usize = m::C;
101+
fn f<const N: usize>() -> [u8; N] { [0; N] }
102+
103+
let _ = f::<42>(); // Literal.
104+
let _: [_; 42] = f::<_>(); // Inferred const.
105+
let _: [_; 42] = f::<(((_)))>(); // Inferred const.
106+
let _ = f::<C>(); // Single segment path.
107+
let _ = f::<{ m::C }>(); // Multi-segment path must be braced.
108+
```
109+
110+
> [!NOTE]
111+
> An [inferred const] is parsed as an [inferred type] but then semantically treated as a separate kind of [const generic argument].
96112
97113
r[paths.expr.impl-trait-params]
98114
The synthetic type parameters corresponding to `impl Trait` types are implicit,
@@ -480,10 +496,13 @@ mod without { // crate::without
480496
[`Self` scope]: names/scopes.md#self-scope
481497
[`use`]: items/use-declarations.md
482498
[attributes]: attributes.md
499+
[const generic argument]: items.generics.const.argument
483500
[enumeration]: items/enumerations.md
484501
[expressions]: expressions.md
485502
[extern prelude]: names/preludes.md#extern-prelude
486503
[implementation]: items/implementations.md
504+
[inferred const]: items.generics.const.inferred
505+
[inferred type]: type.inferred
487506
[macro transcribers]: macros-by-example.md
488507
[macros]: macros.md
489508
[mbe]: macros-by-example.md

0 commit comments

Comments
 (0)