Skip to content

Commit 798b26a

Browse files
Update resolved/unresolved questions in RFC
- "Generic parameters" are resolved to work just like array length expressions. - Added section about containing `unsafe` blocks. - Moved "lints" to unresolved questions.
1 parent e67c40b commit 798b26a

File tree

1 file changed

+75
-53
lines changed

1 file changed

+75
-53
lines changed

text/0000-inline-const.md

Lines changed: 75 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,19 @@ impl need to use a named `const` declaration.
9191
# Guide-level explanation
9292
[guide-level-explanation]: #guide-level-explanation
9393

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.
96107

97108
```rust
98109
fn foo(x: &i32) -> &i32 {
@@ -104,10 +115,6 @@ fn foo() -> &u32 {
104115
}
105116
```
106117

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-
111118
## Patterns
112119

113120
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,
190197
> | ConstBlockExpression // new
191198
> ```
192199
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.
197213
198214
```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+
}
200219
```
201220
202-
where `Ty` is inferred from the expression inside the braces.
221+
## Containing `unsafe`
203222

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:
206224

207225
```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+
}
214231
```
215232

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:
219236

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+
```
223244

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
227249

228250
# Drawbacks
229251
[drawbacks]: #drawbacks
@@ -265,27 +287,6 @@ AFAIK, this was [first proposed] by **@scottmcm**.
265287
# Unresolved questions
266288
[unresolved-questions]: #unresolved-questions
267289

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-
289290
## Naming
290291

291292
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
303304

304305
[RFC 2526]: https://github.com/rust-lang/rfcs/pull/2526
305306

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]`.
307328

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.
310332

311333
# Future possibilities
312334
[future possibilities]: #future-possibilities

0 commit comments

Comments
 (0)