-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inline const
expressions and patterns
#2920
Conversation
Co-authored-by: Martin Carton <[email protected]>
Thanks for writing this up, @ecstatic-morse! The const-eval group's excellent promotion rules document you linked made me want this even more than I originally thought, as having a visible way to opt-in (and thus not need to worry about whether it is, isn't, or should be happening) seems so much better than trying to extend something that's already quite complicated. |
prior art: Zig has a "comptime" mechanism, https://kristoff.it/blog/what-is-zig-comptime/ |
For the record, I am in favor of a single-expression, braceless variant like |
I feel somewhat strongly that for this RFC, We can talk about (I would plausibly think otherwise if |
`const` expressions inside a `const` or `static` is also an open question. | ||
|
||
# Drawbacks | ||
[drawbacks]: #drawbacks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this is a drawback or a complication, but I presume this would also work in generic contexts -- so we would be basically introducing generic consts with this RFC. Well, we already have consts in generic contexts with associated consts, but they don't work quite as well as other consts in terms of linting etc -- we have monomorphization-time errors because only then can we actually evaluate the const. The same would likely happen here, right?
fn aptr::<T>() -> &'static *mut T {
const { &std::ptr::NonNull::dangling().as_ptr() }
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is an excellent point. My initial thought was that we would indeed prevent inline constants from referring to generic parameters, just as constants currently do. If we allow this for inline constants, why not allow it for named constants as well? Are there backwards compatibility concerns?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we accept this RFC without allowing inline constants to refer to in-scope generic parameters, there will be a narrow class of implicitly promotable expressions (e.g. std::ptr::null::<T>()
, T::CONST + T::ANOTHER_CONST
) that couldn't be written in const blocks. I don't expect a ton of code is depending on the promotability of expressions such as these, but it makes it more difficult to justify the deprecation of implicit promotion for all fn
calls and arithmetic expressions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we accept this RFC without allowing inline constants to refer to in-scope generic parameters, there will be a narrow class of implicitly promotable expressions [...]
Exactly, that's why my gut feeling is we should allow generics.
We have to figure out better how to lint wrong CTFE in potentially generic consts -- maybe we can eagerly evaluate at least those that do not actually depend on a generic parameter -- but that seems like a concern to be figured out during implementation.
If we allow this for inline constants, why not allow it for named constants as well? Are there backwards compatibility concerns?
For once, we'd need syntax, which is not the case for inline consts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we can backwards compatibly allow inline constants to refer to in-scope generic parameters in the future, I would like to separate that feature from the initial implementation. We would need both things before we considered deprecating the promotion of arithmetic expressions, but that doesn't mean they need to be spec'ed/implemented together.
text/0000-inline-const.md
Outdated
|
||
It would also possible to separate out the parts of this RFC relating to patterns | ||
so that they can be decided upon seperately. I think they are similar enough | ||
that they are best considered as a unit, however. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that so far we do not do implicit promotion in patterns, I feel it makes sense to go baby steps here and start with inline consts (anonymous consts?) as expressions only to match the existing implicit promotion in expressions -- so IMO they should be made separate feature gates and stabilization considered separately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For me, the overarching principles of this RFC should be:
- inline consts behave exactly the same as if you defined a named constant in the same scope.
- inline consts can be used anywhere you would use a named constant.
These rules of thumb help make this feature easy to reason about. Since you can already use named constants in patterns, I don't see any reason you shouldn't be allowed to use inline ones.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The RFC describes inline consts as sugar for { const NAME := ...; NAME }
; that expansion would not work in patterns as they are not expressions.
I feel like patterns and expressions are sufficiently different that there is no reason to tie them together like that. For expressions we have concrete cases and this has been floated for years; for patterns this is the first time I see it and frankly I find it syntactically rather awkward.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The RFC describes inline consts as sugar for { const NAME := ...; NAME }; that expansion would not work in patterns as they are not expressions.
This is not news to me. The RFC states explicitly that that analogy is only valid in expression context. The real desugaring is less elegant–define a new constant with a unique name in the same scope as the inline const
and then refer to the newly defined constant–but operationally the same. I don't think it's too big of a stretch to go from one to the other.
The rest is a matter of opinion. I find the consistency argument compelling, and I don't think wanting to match on the result of a const fn
is all that novel, although admittedly my examples aren't very convincing. Perhaps someone has a better example of code using one-off named constants in patterns that would benefit from this RFC?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rest is a matter of opinion.
That is definitely so. :)
I am just asking that the RFC list arguments both way -- right now it lists your arguments but not mine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(From what I can see, the RFC still lists no arguments in favor of separating patterns.)
text/0000-inline-const.md
Outdated
In both the expression and pattern context, an inline `const` behaves exactly | ||
as if the user had declared a uniquely identified `const` with the block's | ||
contents as its initializer. For example, in expression context, writing | ||
`const { ... }` is equivalent to writing: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is truly an equivalence, then these consts would not be able to access generics of the surrounding function. That's a fine first step, but implicit promotion can access those generics, so it would not be a full replacement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there any implementation concerns with accessing generic parameters? I understand that that rules for items prevent it, but it would seem very odd for expressions to be unable to access generic parameters -- by analogy, you can reference generic parameters in an async{}
even though you cannot reference them in a nested async fn
.
I think this analogy would be reasonable in a guide-level intuition argument, but shouldn't be how it's actually defined.
🔔 This is now entering its final comment period, as per the review above. 🔔 |
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. The RFC will be merged soon. |
@nikomatsakis FCP "merge" is complete here. Any chance you could merge this? :D |
@RalfJung raised an interesting question a while ago that I'm just now reading: Should the following code emit a fn div() -> &'static i32 {
const C: i32 = 0;
if C != 0 {
const { &(42 / C) } // Does this emit `const_err`?
} else {
&0
}
} While it might be possible to skip I think we would be able to relax this rule at a later date if there was a compelling use-case, since always emitting Does this match people's expectations? |
How is that possible? It's a const, after all... EDIT: oh you said "condition", not the const. Using an erroneous OTOH, for promoteds, we do not make CTFE failure a hard error. In my opinion, we should only promote things that cannot fail to evaluate, thus side-stepping this problem. So, my opinion is that it should be a hard error (not just a |
Huzzah! The @rust-lang/lang team has decided to accept this RFC. You can follow along with development on the tracking issue, rust-lang/rust#76001. |
Stabilise inline_const # Stabilisation Report ## Summary This PR will stabilise `inline_const` feature in expression position. `inline_const_pat` is still unstable and will *not* be stabilised. The feature will allow code like this: ```rust foo(const { 1 + 1 }) ``` which is roughly desugared into ```rust struct Foo; impl Foo { const FOO: i32 = 1 + 1; } foo(Foo::FOO) ``` This feature is from rust-lang/rfcs#2920 and is tracked in rust-lang#76001 (the tracking issue should *not* be closed as it needs to track inline const in pattern position). The initial implementation is done in rust-lang#77124. ## Difference from RFC There are two major differences (enhancements) as implemented from the RFC. First thing is that the RFC says that the type of an inline const block inferred from the content *within* it, but we currently can infer the type using the information from outside the const block as well. This is a frequently requested feature to the initial implementation (e.g. rust-lang#89964). The inference is implemented in rust-lang#89561 and is done by treating inline const similar to a closure and therefore share inference context with its parent body. This allows code like: ```rust let v: Vec<i32> = const { Vec::new() }; ``` Another enhancement that differs from the RFC is that we currently allow inline consts to reference generic parameters. This is implemented in rust-lang#96557. This allows code like: ```rust fn create_none_array<T, const N: usize>() -> [Option<T>; N] { [const { None::<T> }; N] } ``` This enhancement also makes inline const usable as static asserts: ```rust fn require_zst<T>() { const { assert!(std::mem::size_of::<T>() == 0) } } ``` ## Documentation Reference: rust-lang/reference#1295 ## Unresolved issues We still have a few issues that are not resolved, but I don't think it necessarily has to block stabilisation: * expr fragment specifier issue: rust-lang#86730 * ~~`const {}` behaves similar to `async {}` but not to `{}` and `unsafe {}` (they are treated as `ExpressionWithoutBlock` rather than `ExpressionWithBlock`): https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/const.20blocks.20differ.20from.20normal.20and.20from.20unsafe.20blocks/near/290229453~~ ## Tests There are a few tests in https://github.com/rust-lang/rust/tree/master/src/test/ui/inline-const
Stabilise inline_const # Stabilisation Report ## Summary This PR will stabilise `inline_const` feature in expression position. `inline_const_pat` is still unstable and will *not* be stabilised. The feature will allow code like this: ```rust foo(const { 1 + 1 }) ``` which is roughly desugared into ```rust struct Foo; impl Foo { const FOO: i32 = 1 + 1; } foo(Foo::FOO) ``` This feature is from rust-lang/rfcs#2920 and is tracked in rust-lang#76001 (the tracking issue should *not* be closed as it needs to track inline const in pattern position). The initial implementation is done in rust-lang#77124. ## Difference from RFC There are two major differences (enhancements) as implemented from the RFC. First thing is that the RFC says that the type of an inline const block inferred from the content *within* it, but we currently can infer the type using the information from outside the const block as well. This is a frequently requested feature to the initial implementation (e.g. rust-lang#89964). The inference is implemented in rust-lang#89561 and is done by treating inline const similar to a closure and therefore share inference context with its parent body. This allows code like: ```rust let v: Vec<i32> = const { Vec::new() }; ``` Another enhancement that differs from the RFC is that we currently allow inline consts to reference generic parameters. This is implemented in rust-lang#96557. This allows code like: ```rust fn create_none_array<T, const N: usize>() -> [Option<T>; N] { [const { None::<T> }; N] } ``` This enhancement also makes inline const usable as static asserts: ```rust fn require_zst<T>() { const { assert!(std::mem::size_of::<T>() == 0) } } ``` ## Documentation Reference: rust-lang/reference#1295 ## Unresolved issues We still have a few issues that are not resolved, but I don't think it necessarily has to block stabilisation: * expr fragment specifier issue: rust-lang#86730 * ~~`const {}` behaves similar to `async {}` but not to `{}` and `unsafe {}` (they are treated as `ExpressionWithoutBlock` rather than `ExpressionWithBlock`): https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/const.20blocks.20differ.20from.20normal.20and.20from.20unsafe.20blocks/near/290229453~~ ## Tests There are a few tests in https://github.com/rust-lang/rust/tree/master/src/test/ui/inline-const
Stabilise inline_const # Stabilisation Report ## Summary This PR will stabilise `inline_const` feature in expression position. `inline_const_pat` is still unstable and will *not* be stabilised. The feature will allow code like this: ```rust foo(const { 1 + 1 }) ``` which is roughly desugared into ```rust struct Foo; impl Foo { const FOO: i32 = 1 + 1; } foo(Foo::FOO) ``` This feature is from rust-lang/rfcs#2920 and is tracked in rust-lang#76001 (the tracking issue should *not* be closed as it needs to track inline const in pattern position). The initial implementation is done in rust-lang#77124. ## Difference from RFC There are two major differences (enhancements) as implemented from the RFC. First thing is that the RFC says that the type of an inline const block inferred from the content *within* it, but we currently can infer the type using the information from outside the const block as well. This is a frequently requested feature to the initial implementation (e.g. rust-lang#89964). The inference is implemented in rust-lang#89561 and is done by treating inline const similar to a closure and therefore share inference context with its parent body. This allows code like: ```rust let v: Vec<i32> = const { Vec::new() }; ``` Another enhancement that differs from the RFC is that we currently allow inline consts to reference generic parameters. This is implemented in rust-lang#96557. This allows code like: ```rust fn create_none_array<T, const N: usize>() -> [Option<T>; N] { [const { None::<T> }; N] } ``` This enhancement also makes inline const usable as static asserts: ```rust fn require_zst<T>() { const { assert!(std::mem::size_of::<T>() == 0) } } ``` ## Documentation Reference: rust-lang/reference#1295 ## Unresolved issues We still have a few issues that are not resolved, but I don't think it necessarily has to block stabilisation: * expr fragment specifier issue: rust-lang#86730 * ~~`const {}` behaves similar to `async {}` but not to `{}` and `unsafe {}` (they are treated as `ExpressionWithoutBlock` rather than `ExpressionWithBlock`): https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/const.20blocks.20differ.20from.20normal.20and.20from.20unsafe.20blocks/near/290229453~~ ## Tests There are a few tests in https://github.com/rust-lang/rust/tree/master/src/test/ui/inline-const
Stabilise inline_const # Stabilisation Report ## Summary This PR will stabilise `inline_const` feature in expression position. `inline_const_pat` is still unstable and will *not* be stabilised. The feature will allow code like this: ```rust foo(const { 1 + 1 }) ``` which is roughly desugared into ```rust struct Foo; impl Foo { const FOO: i32 = 1 + 1; } foo(Foo::FOO) ``` This feature is from rust-lang/rfcs#2920 and is tracked in rust-lang#76001 (the tracking issue should *not* be closed as it needs to track inline const in pattern position). The initial implementation is done in rust-lang#77124. ## Difference from RFC There are two major differences (enhancements) as implemented from the RFC. First thing is that the RFC says that the type of an inline const block inferred from the content *within* it, but we currently can infer the type using the information from outside the const block as well. This is a frequently requested feature to the initial implementation (e.g. rust-lang#89964). The inference is implemented in rust-lang#89561 and is done by treating inline const similar to a closure and therefore share inference context with its parent body. This allows code like: ```rust let v: Vec<i32> = const { Vec::new() }; ``` Another enhancement that differs from the RFC is that we currently allow inline consts to reference generic parameters. This is implemented in rust-lang#96557. This allows code like: ```rust fn create_none_array<T, const N: usize>() -> [Option<T>; N] { [const { None::<T> }; N] } ``` This enhancement also makes inline const usable as static asserts: ```rust fn require_zst<T>() { const { assert!(std::mem::size_of::<T>() == 0) } } ``` ## Documentation Reference: rust-lang/reference#1295 ## Unresolved issues We still have a few issues that are not resolved, but I don't think it necessarily has to block stabilisation: * expr fragment specifier issue: rust-lang#86730 * ~~`const {}` behaves similar to `async {}` but not to `{}` and `unsafe {}` (they are treated as `ExpressionWithoutBlock` rather than `ExpressionWithBlock`): https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/const.20blocks.20differ.20from.20normal.20and.20from.20unsafe.20blocks/near/290229453~~ ## Tests There are a few tests in https://github.com/rust-lang/rust/tree/master/src/test/ui/inline-const
Stabilise inline_const # Stabilisation Report ## Summary This PR will stabilise `inline_const` feature in expression position. `inline_const_pat` is still unstable and will *not* be stabilised. The feature will allow code like this: ```rust foo(const { 1 + 1 }) ``` which is roughly desugared into ```rust struct Foo; impl Foo { const FOO: i32 = 1 + 1; } foo(Foo::FOO) ``` This feature is from rust-lang/rfcs#2920 and is tracked in rust-lang#76001 (the tracking issue should *not* be closed as it needs to track inline const in pattern position). The initial implementation is done in rust-lang#77124. ## Difference from RFC There are two major differences (enhancements) as implemented from the RFC. First thing is that the RFC says that the type of an inline const block inferred from the content *within* it, but we currently can infer the type using the information from outside the const block as well. This is a frequently requested feature to the initial implementation (e.g. rust-lang#89964). The inference is implemented in rust-lang#89561 and is done by treating inline const similar to a closure and therefore share inference context with its parent body. This allows code like: ```rust let v: Vec<i32> = const { Vec::new() }; ``` Another enhancement that differs from the RFC is that we currently allow inline consts to reference generic parameters. This is implemented in rust-lang#96557. This allows code like: ```rust fn create_none_array<T, const N: usize>() -> [Option<T>; N] { [const { None::<T> }; N] } ``` This enhancement also makes inline const usable as static asserts: ```rust fn require_zst<T>() { const { assert!(std::mem::size_of::<T>() == 0) } } ``` ## Documentation Reference: rust-lang/reference#1295 ## Unresolved issues We still have a few issues that are not resolved, but I don't think it necessarily has to block stabilisation: * expr fragment specifier issue: rust-lang#86730 * ~~`const {}` behaves similar to `async {}` but not to `{}` and `unsafe {}` (they are treated as `ExpressionWithoutBlock` rather than `ExpressionWithBlock`): https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/const.20blocks.20differ.20from.20normal.20and.20from.20unsafe.20blocks/near/290229453~~ ## Tests There are a few tests in https://github.com/rust-lang/rust/tree/master/src/test/ui/inline-const
Stabilise inline_const # Stabilisation Report ## Summary This PR will stabilise `inline_const` feature in expression position. `inline_const_pat` is still unstable and will *not* be stabilised. The feature will allow code like this: ```rust foo(const { 1 + 1 }) ``` which is roughly desugared into ```rust struct Foo; impl Foo { const FOO: i32 = 1 + 1; } foo(Foo::FOO) ``` This feature is from rust-lang/rfcs#2920 and is tracked in rust-lang#76001 (the tracking issue should *not* be closed as it needs to track inline const in pattern position). The initial implementation is done in rust-lang#77124. ## Difference from RFC There are two major differences (enhancements) as implemented from the RFC. First thing is that the RFC says that the type of an inline const block inferred from the content *within* it, but we currently can infer the type using the information from outside the const block as well. This is a frequently requested feature to the initial implementation (e.g. rust-lang#89964). The inference is implemented in rust-lang#89561 and is done by treating inline const similar to a closure and therefore share inference context with its parent body. This allows code like: ```rust let v: Vec<i32> = const { Vec::new() }; ``` Another enhancement that differs from the RFC is that we currently allow inline consts to reference generic parameters. This is implemented in rust-lang#96557. This allows code like: ```rust fn create_none_array<T, const N: usize>() -> [Option<T>; N] { [const { None::<T> }; N] } ``` This enhancement also makes inline const usable as static asserts: ```rust fn require_zst<T>() { const { assert!(std::mem::size_of::<T>() == 0) } } ``` ## Documentation Reference: rust-lang/reference#1295 ## Unresolved issues We still have a few issues that are not resolved, but I don't think it necessarily has to block stabilisation: * expr fragment specifier issue: rust-lang#86730 * ~~`const {}` behaves similar to `async {}` but not to `{}` and `unsafe {}` (they are treated as `ExpressionWithoutBlock` rather than `ExpressionWithBlock`): https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/const.20blocks.20differ.20from.20normal.20and.20from.20unsafe.20blocks/near/290229453~~ ## Tests There are a few tests in https://github.com/rust-lang/rust/tree/master/src/test/ui/inline-const
Stabilise inline_const # Stabilisation Report ## Summary This PR will stabilise `inline_const` feature in expression position. `inline_const_pat` is still unstable and will *not* be stabilised. The feature will allow code like this: ```rust foo(const { 1 + 1 }) ``` which is roughly desugared into ```rust struct Foo; impl Foo { const FOO: i32 = 1 + 1; } foo(Foo::FOO) ``` This feature is from rust-lang/rfcs#2920 and is tracked in rust-lang#76001 (the tracking issue should *not* be closed as it needs to track inline const in pattern position). The initial implementation is done in rust-lang#77124. ## Difference from RFC There are two major differences (enhancements) as implemented from the RFC. First thing is that the RFC says that the type of an inline const block inferred from the content *within* it, but we currently can infer the type using the information from outside the const block as well. This is a frequently requested feature to the initial implementation (e.g. rust-lang#89964). The inference is implemented in rust-lang#89561 and is done by treating inline const similar to a closure and therefore share inference context with its parent body. This allows code like: ```rust let v: Vec<i32> = const { Vec::new() }; ``` Another enhancement that differs from the RFC is that we currently allow inline consts to reference generic parameters. This is implemented in rust-lang#96557. This allows code like: ```rust fn create_none_array<T, const N: usize>() -> [Option<T>; N] { [const { None::<T> }; N] } ``` This enhancement also makes inline const usable as static asserts: ```rust fn require_zst<T>() { const { assert!(std::mem::size_of::<T>() == 0) } } ``` ## Documentation Reference: rust-lang/reference#1295 ## Unresolved issues We still have a few issues that are not resolved, but I don't think it necessarily has to block stabilisation: * expr fragment specifier issue: rust-lang#86730 * ~~`const {}` behaves similar to `async {}` but not to `{}` and `unsafe {}` (they are treated as `ExpressionWithoutBlock` rather than `ExpressionWithBlock`): https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/const.20blocks.20differ.20from.20normal.20and.20from.20unsafe.20blocks/near/290229453~~ ## Tests There are a few tests in https://github.com/rust-lang/rust/tree/master/src/test/ui/inline-const
Stabilise inline_const # Stabilisation Report ## Summary This PR will stabilise `inline_const` feature in expression position. `inline_const_pat` is still unstable and will *not* be stabilised. The feature will allow code like this: ```rust foo(const { 1 + 1 }) ``` which is roughly desugared into ```rust struct Foo; impl Foo { const FOO: i32 = 1 + 1; } foo(Foo::FOO) ``` This feature is from rust-lang/rfcs#2920 and is tracked in #76001 (the tracking issue should *not* be closed as it needs to track inline const in pattern position). The initial implementation is done in #77124. ## Difference from RFC There are two major differences (enhancements) as implemented from the RFC. First thing is that the RFC says that the type of an inline const block inferred from the content *within* it, but we currently can infer the type using the information from outside the const block as well. This is a frequently requested feature to the initial implementation (e.g. #89964). The inference is implemented in #89561 and is done by treating inline const similar to a closure and therefore share inference context with its parent body. This allows code like: ```rust let v: Vec<i32> = const { Vec::new() }; ``` Another enhancement that differs from the RFC is that we currently allow inline consts to reference generic parameters. This is implemented in #96557. This allows code like: ```rust fn create_none_array<T, const N: usize>() -> [Option<T>; N] { [const { None::<T> }; N] } ``` This enhancement also makes inline const usable as static asserts: ```rust fn require_zst<T>() { const { assert!(std::mem::size_of::<T>() == 0) } } ``` ## Documentation Reference: rust-lang/reference#1295 ## Unresolved issues We still have a few issues that are not resolved, but I don't think it necessarily has to block stabilisation: * expr fragment specifier issue: #86730 * ~~`const {}` behaves similar to `async {}` but not to `{}` and `unsafe {}` (they are treated as `ExpressionWithoutBlock` rather than `ExpressionWithBlock`): https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/const.20blocks.20differ.20from.20normal.20and.20from.20unsafe.20blocks/near/290229453~~ ## Tests There are a few tests in https://github.com/rust-lang/rust/tree/master/src/test/ui/inline-const
Rendered
TL; DR: Allows users to request compile-time evaluation without requiring promotion or a named
const
.This idea has been in the ether for a while now as a way to reduce dependence on promotion for evaluating simple expressions at compile-time. It was discussed most recently on Zulip.
Credit to @scottmcm, who discussed this with me on Zulip and was one of the people who discovered this idea. I believe both @RalfJung and @oli-obk have considered this as well.