You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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 in various places to make this all as clear as possible.
Copy file name to clipboardExpand all lines: src/expressions/array-expr.md
+14-1Lines changed: 14 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -35,7 +35,18 @@ r[expr.array.length-operand]
35
35
The expression after the `;` is called the *length operand*.
36
36
37
37
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]).
39
+
40
+
```rust
41
+
constC:usize=1;
42
+
let_: [u8; C] = [0; 1]; // Literal.
43
+
let_: [u8; C] = [0; C]; // Constant item.
44
+
let_: [u8; C] = [0; _]; // Inferred const.
45
+
let_: [u8; C] = [0; (((_)))]; // Inferred const.
46
+
```
47
+
48
+
> [!NOTE]
49
+
> In an array expression, an [inferred const] is parsed as an [expression][Expression] but then semantically treated as a separate kind of [const generic argument].
39
50
40
51
r[expr.array.repeat-behavior]
41
52
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.
@@ -111,8 +122,10 @@ The array index expression can be implemented for types other than arrays and sl
A const argument in a [path] specifies the const value to use for that item.
147
147
148
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).
149
+
The argument must either be an [inferred const] or be a [const expression] of the type ascribed to the const parameter. The const expression must be a [block expression][block] (surrounded with braces) unless it is a single path segment (an [IDENTIFIER]) or a [literal] (with a possibly leading `-` token).
153
150
154
151
> [!NOTE]
155
152
> This syntactic restriction is necessary to avoid requiring infinite lookahead when parsing an expression inside of a type.
156
153
157
154
```rust
158
-
fndouble<constN:i32>() {
159
-
println!("doubled: {}", N*2);
160
-
}
161
-
162
-
constSOME_CONST:i32=12;
163
-
164
-
fnexample() {
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
-
}
155
+
structS<constN:i64>;
156
+
constC:i64=1;
157
+
fnf<constN:i64>() ->S<N> { S }
158
+
159
+
let_=f::<1>(); // Literal.
160
+
let_=f::<-1>(); // Negative literal.
161
+
let_=f::<{ 1+2 }>(); // Constant expression.
162
+
let_=f::<C>(); // Single segment path.
163
+
let_=f::<{ C+1 }>(); // Constant expression.
164
+
let_:S<1> =f::<_>(); // Inferred const.
165
+
let_:S<1> =f::<(((_)))>(); // Inferred const.
172
166
```
173
167
168
+
> [!NOTE]
169
+
> In a generic argument list, an [inferred const] is parsed as an [inferred type][InferredType] but then semantically treated as a separate kind of [const generic argument].
170
+
174
171
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.
172
+
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], [array expression rules][expr.array.length-restriction]), can be used instead. This asks the compiler to infer the const argument if possible based on surrounding information.
176
173
177
174
```rust
178
-
fnmake_buf() -> [u8; 1024] {
179
-
[0x1; _]
180
-
//^ Infers `1024`.
175
+
fnmake_buf<constN:usize>() -> [u8; N] {
176
+
[0; _]
177
+
// ^ Infers `N`.
181
178
}
179
+
let_: [u8; 1024] =make_buf::<_>();
180
+
// ^ Infers `1024`.
182
181
```
183
182
183
+
> [!NOTE]
184
+
> An [inferred const] is not semantically an [expression][Expression] and so is not accepted within braces.
185
+
>
186
+
> ```rust,compile_fail
187
+
> fn f<const N: usize>() -> [u8; N] { [0; _] }
188
+
> let _: [_; 1] = f::<{ _ }>();
189
+
> // ^ ERROR `_` not allowed here
190
+
> ```
191
+
184
192
r[items.generics.const.inferred.constraint]
185
-
It cannot be used in item signatures.
193
+
The inferred const cannot be used in item signatures.
194
+
195
+
```rust,compile_fail
196
+
fn f<const N: usize>(x: [u8; N]) -> [u8; _] { x }
197
+
// ^ ERROR not allowed
198
+
```
186
199
187
200
r[items.generics.const.type-ambiguity]
188
201
When there is ambiguity if a generic argument could be resolved as either a
Copy file name to clipboardExpand all lines: src/paths.md
+20-2Lines changed: 20 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -91,8 +91,24 @@ The order of generic arguments is restricted to lifetime arguments, then type
91
91
arguments, then const arguments, then equality constraints.
92
92
93
93
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
+
modm {
98
+
pubconstC:usize=1;
99
+
}
100
+
constC:usize=m::C;
101
+
fnf<constN:usize>() -> [u8; N] { [0; N] }
102
+
103
+
let_=f::<1>(); // Literal.
104
+
let_: [_; 1] =f::<_>(); // Inferred const.
105
+
let_: [_; 1] =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
+
> In a generic argument list, an [inferred const] is parsed as an [inferred type][InferredType] but then semantically treated as a separate kind of [const generic argument].
96
112
97
113
r[paths.expr.impl-trait-params]
98
114
The synthetic type parameters corresponding to `impl Trait` types are implicit,
@@ -480,10 +496,12 @@ mod without { // crate::without
0 commit comments