@@ -91,8 +91,19 @@ impl need to use a named `const` declaration.
91
91
# Guide-level explanation
92
92
[ guide-level-explanation ] : #guide-level-explanation
93
93
94
- This proposal is a middle ground, which is less verbose than named constants but
95
- more obvious and expressive than promotion.
94
+ This proposal is a middle ground, which is less verbose than named constants
95
+ but more obvious and expressive than promotion. In expression context, it
96
+ behaves much like the user had written the following, where ` Ty ` is the
97
+ inferred type of the code within the inline ` const ` expression (represented by
98
+ the ellipsis):
99
+
100
+ ``` rust
101
+ { const UNIQUE_IDENT : Ty = ... ; UNIQUE_IDENT }
102
+ ```
103
+
104
+ With this extension to the language, users can ensure that their code executes
105
+ at compile-time without needing to declare a separate ` const ` item that is only
106
+ used once.
96
107
97
108
``` rust
98
109
fn foo (x : & i32 ) -> & i32 {
@@ -104,10 +115,6 @@ fn foo() -> &u32 {
104
115
}
105
116
```
106
117
107
- With this extension to the language, users can ensure that their code executes
108
- at compile-time without needing to declare a separate ` const ` item that is only
109
- used once.
110
-
111
118
## Patterns
112
119
113
120
Patterns are another context that require a named ` const ` when using complex
@@ -190,40 +197,55 @@ This RFC extends the [grammar for patterns] to be,
190
197
> | ConstBlockExpression // new
191
198
> ```
192
199
193
- In both the expression and pattern context, an inline `const` behaves exactly
194
- as if the user had declared a uniquely identified `const` with the block's
195
- contents as its initializer. For example, in expression context, writing
196
- `const { ... }` is equivalent to writing:
200
+ In both the expression and pattern context, an inline `const` behaves as if the
201
+ user had declared a uniquely named constant in the containing scope and
202
+ referenced it.
203
+
204
+ ## Generic Parameters
205
+
206
+ For now, inline `const` expressions and patterns cannot refer to in-scope
207
+ generic parameters. As of this writing, the same restriction applies to array
208
+ length expressions, which seem like a good precedent for this RFC. As far as I
209
+ know, this is only a temporary restriction; the long-term goal is to allow
210
+ array length expressions to use generic parameters. When this happens, inline
211
+ `const` expressions and patterns will also be allowed to refer to in-scope
212
+ generics.
197
213
198
214
```rust
199
- { const UNIQUE_IDENT: Ty = ...; UNIQUE_IDENT }
215
+ fn foo<T>() {
216
+ let x = [4i32; std::mem::size_of::<T>()]; // NOT ALLOWED (for now)
217
+ let x = const { std::mem::size_of::<T>() }; // NOT ALLOWED (for now)
218
+ }
200
219
```
201
220
202
- where ` Ty ` is inferred from the expression inside the braces.
221
+ ## Containing ` unsafe `
203
222
204
- An inline ` const ` is eligible for promotion in an implicit context (just like a
205
- named ` const ` ), so the following are all guaranteed to work:
223
+ At present, containing ` unsafe ` blocks do not apply to array length expressions inside:
206
224
207
225
``` rust
208
- let x : & 'static i32 = & const { 4i32 . pow (4 ) };
209
- let x : & 'static i32 = const { & 4i32 . pow (4 ) };
210
-
211
- // If RFC 2203 is stabilized
212
- let v = [const { Vec :: new () }; 3 ];
213
- let v = const { [Vec :: new (); 3 ] };
226
+ fn bar () {
227
+ let x = unsafe {
228
+ [4i32 ; std :: intrinsics :: unchecked_add (2i32 , 3i32 )] // ERROR
229
+ };
230
+ }
214
231
```
215
232
216
- I don't have strong feelings about which version should be preferred.
217
- ** @ RalfJung ** points out that ` &const { 4 + 2 } ` is more readable than `const {
218
- &(4 + 2) }`.
233
+ I find this somewhat strange, but consistency is important, so inline ` const `
234
+ expressions should behave the same way. The following would also fail to
235
+ compile:
219
236
220
- Note that it may be possible for RFC 2203 to use the explicit rules for
221
- promotability when ` T: !Copy ` . In this case, the last part of the example above
222
- could simply be written as ` [Vec::new(); 3] ` .
237
+ ``` rust
238
+ fn bar () {
239
+ let x = unsafe {
240
+ const { std :: intrinsics :: unchecked_add (2i32 , 3i32 ) } // ERROR
241
+ };
242
+ }
243
+ ```
223
244
224
- Inline ` const ` s are allowed within ` const ` and ` static ` initializers, just as we
225
- currently allow nested ` const ` declarations. Whether to lint against inline
226
- ` const ` expressions inside a ` const ` or ` static ` is also an open question.
245
+ If [ #72359 ] is considered a bug and resolved, that change would also apply to
246
+ inline ` const ` expressions and patterns.
247
+
248
+ [ #72359 ] : https://github.com/rust-lang/rust/issues/72359
227
249
228
250
# Drawbacks
229
251
[ drawbacks ] : #drawbacks
@@ -265,27 +287,6 @@ AFAIK, this was [first proposed] by **@scottmcm**.
265
287
# Unresolved questions
266
288
[ unresolved-questions ] : #unresolved-questions
267
289
268
- ## Generic Parameters
269
-
270
- Named constants defined inside a function cannot use generic parameters that
271
- are in scope within that function.
272
-
273
- ``` rust
274
- fn foo <T >() {
275
- const SIZE : usize = { std :: mem :: size_of :: <T >() }; // ERROR
276
- }
277
- ```
278
-
279
- If we use the same rule for inline constants, there would be a class of
280
- implicitly promotable expressions (e.g. ` std::ptr::null::<T>() ` , `T::CONST +
281
- T::ANOTHER_CONST`), that could not be written inside an inline constant. We
282
- would need to resolve this somehow before we stop promoting these expressions
283
- as discussed in [ future possibilites] .
284
-
285
- Alternatively, we could allow inline constants to refer to generic parameters.
286
- Associated constants already behave this way, so I think this is possible.
287
- However, it may result in more post-monomorphization const-eval errors.
288
-
289
290
## Naming
290
291
291
292
I prefer the name inline ` const ` , since it signals that there is no difference
@@ -303,10 +304,31 @@ that this could be confused with the `const _: () = ...;` syntax introduced in
303
304
304
305
[ RFC 2526 ] : https://github.com/rust-lang/rfcs/pull/2526
305
306
306
- ## Lints
307
+ ## Lints about placement of inline ` const `
308
+
309
+ An inline ` const ` is eligible for promotion in an implicit context (just like a
310
+ named ` const ` ), so the following are all guaranteed to work:
311
+
312
+ ``` rust
313
+ let x : & 'static i32 = & const { 4i32 . pow (4 ) };
314
+ let x : & 'static i32 = const { & 4i32 . pow (4 ) };
315
+
316
+ // If RFC 2203 is stabilized
317
+ let v = [const { Vec :: new () }; 3 ];
318
+ let v = const { [Vec :: new (); 3 ] };
319
+ ```
320
+
321
+ I don't have strong feelings about which version should be preferred.
322
+ ** @RalfJung ** points out that ` &const { 4 + 2 } ` is more readable than `const {
323
+ &(4 + 2) }`.
324
+
325
+ Note that it may be possible for RFC 2203 to use the explicit rules for
326
+ promotability when ` T: !Copy ` . In this case, the last part of the example above
327
+ could simply be written as ` [Vec::new(); 3] ` .
307
328
308
- As mentioned in the reference-level specification, we need to decide whether we
309
- want to lint against certain types of inline ` const ` expressions.
329
+ Inline ` const ` s are allowed within ` const ` and ` static ` initializers, just as we
330
+ currently allow nested ` const ` declarations. Whether to lint against inline
331
+ ` const ` expressions inside a ` const ` or ` static ` is also an open question.
310
332
311
333
# Future possibilities
312
334
[ future possibilities ] : #future-possibilities
0 commit comments