@@ -67,36 +67,23 @@ The only allowed types of const parameters are `u8`, `u16`, `u32`, `u64`, `u128`
67
67
` i8 ` , ` i16 ` , ` i32 ` , ` i64 ` , ` i128 ` , ` isize ` , ` char ` and ` bool ` .
68
68
69
69
r[ items.generics.const.usage]
70
- Const parameters can be used anywhere a [ const item] can be used, with the
71
- exception that when used in a [ type] or [ array repeat expression] , it must be
72
- standalone (as described below). That is, they are allowed in the following
73
- places:
74
-
75
- 1 . As an applied const to any type which forms a part of the signature of the
76
- item in question.
77
- 2 . As part of a const expression used to define an [ associated const] , or as a
78
- parameter to an [ associated type] .
79
- 3 . As a value in any runtime expression in the body of any functions in the
80
- item.
81
- 4 . As a parameter to any type used in the body of any functions in the item.
82
- 5 . As a part of the type of any fields in the item.
83
-
70
+ Within an item that has const parameter declarations, the names of the const parameters are values:
84
71
``` rust
85
72
// Examples where const generic parameters can be used.
86
73
87
74
// Used in the signature of the item itself.
88
75
fn foo <const N : usize >(arr : [i32 ; N ]) {
89
- // Used as a type within a function body.
76
+ // Used within a type within a function body.
90
77
let x : [i32 ; N ];
91
- // Used as an expression.
78
+ // Used within an expression.
92
79
println! (" {}" , N * 2 );
93
80
}
94
81
95
- // Used as a field of a struct.
82
+ // Used within a field of a struct.
96
83
struct Foo <const N : usize >([i32 ; N ]);
97
84
98
85
impl <const N : usize > Foo <N > {
99
- // Used as an associated constant.
86
+ // Used within an associated constant.
100
87
const CONST : usize = N * 4 ;
101
88
}
102
89
@@ -105,13 +92,14 @@ trait Trait {
105
92
}
106
93
107
94
impl <const N : usize > Trait for Foo <N > {
108
- // Used as an associated type.
95
+ // Used within an associated type.
109
96
type Output = [i32 ; N ];
110
97
}
111
98
```
112
99
113
100
``` rust,compile_fail
114
- // Examples where const generic parameters cannot be used.
101
+ // Examples where const generic parameters cannot be used as the uses are not
102
+ // within the item defining the const parameter.
115
103
fn foo<const N: usize>() {
116
104
// Cannot use in item definitions within a function body.
117
105
const BAD_CONST: [usize; N] = [1; N];
@@ -124,71 +112,7 @@ fn foo<const N: usize>() {
124
112
}
125
113
```
126
114
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
- ```
115
+ There are limitations around how a const parameter can be used within a const argument ([ const generics] ).
192
116
193
117
r[ items.generics.const.variance]
194
118
Unlike type and lifetime parameters, const parameters can be declared without
@@ -207,26 +131,6 @@ struct Unconstrained;
207
131
impl<const N: usize> Unconstrained {}
208
132
```
209
133
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
-
230
134
r[ items.generics.where]
231
135
## Where clauses
232
136
@@ -290,10 +194,10 @@ struct Foo<#[my_flexible_clone(unbounded)] H> {
290
194
[ associated const ] : associated-items.md#associated-constants
291
195
[ associated type ] : associated-items.md#associated-types
292
196
[ attributes ] : ../attributes.md
293
- [ block ] : ../expressions/block-expr.md
294
197
[ const contexts ] : ../const_eval.md#const-context
295
198
[ const expression ] : ../const_eval.md#constant-expressions
296
199
[ const item ] : constant-items.md
200
+ [ const generics ] : ../const-generics.md
297
201
[ enumerations ] : enumerations.md
298
202
[ functions ] : functions.md
299
203
[ function pointers ] : ../types/function-pointer.md
@@ -303,7 +207,6 @@ struct Foo<#[my_flexible_clone(unbounded)] H> {
303
207
[ implementations ] : implementations.md
304
208
[ item declarations ] : ../statements.md#item-declarations
305
209
[ item ] : ../items.md
306
- [ literal ] : ../expressions/literal-expr.md
307
210
[ path ] : ../paths.md
308
211
[ path expression ] : ../expressions/path-expr.md
309
212
[ raw pointers ] : ../types/pointer.md#raw-pointers-const-and-mut
@@ -315,4 +218,4 @@ struct Foo<#[my_flexible_clone(unbounded)] H> {
315
218
[ type aliases ] : type-aliases.md
316
219
[ type ] : ../types.md
317
220
[ unions ] : unions.md
318
- [ value namespace ] : ../names/namespaces.md
221
+ [ value namespace ] : ../names/namespaces.md
0 commit comments