-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Implement const expressions and patterns (RFC 2920) #77124
Conversation
r? @oli-obk (rust_highfive has picked a reviewer for you, use r? to override) |
08c9df0
to
18712dd
Compare
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.
I would personally somewhat strongly prefer a different expression name here, for example InlineConst
. AnonConst
is already in use to describe all unnamed constants (array lengths etc) of which
these expressions are only a subset.
[u8; 3 + 4]
^^^^^^
StructFoo<{3 + 7}>
^^^^^^
Apart from this I think these changes look good
2ca921d
to
d56e67b
Compare
This comment has been minimized.
This comment has been minimized.
39e8252
to
9af38b0
Compare
☀️ Test successful - checks-actions, checks-azure |
I've tried:
It gave me errors:
|
@leonardo-m You should probably open a new issue about that. |
OK, filed as #78108 |
self.s.word_space("const"); | ||
self.s.word("{"); | ||
self.print_anon_const(anon_const); | ||
self.s.word("}"); |
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.
Similarly to AST printing, the expr
is already a block, printing the braces again shouldn't be necessary.
@@ -545,6 +546,11 @@ impl<'a> Parser<'a> { | |||
self.check_or_expected(self.token.can_begin_const_arg(), TokenType::Const) | |||
} | |||
|
|||
fn check_inline_const(&mut self) -> bool { | |||
self.check_keyword(kw::Const) | |||
&& self.look_ahead(1, |t| t == &token::OpenDelim(DelimToken::Brace)) |
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.
token::NtBlock
should probably also work as a next token.
(At least it will be successfully parsed by parse_const_expr
.)
One use case I've found in my code:
Rustc could suggest to write that when a programmer tries to write:
|
…r=petrochenkov Inline const followups r? @petrochenkov Follow ups of rust-lang#77124
…r=petrochenkov Inline const followups r? @petrochenkov Follow ups of rust-lang#77124
…t, r=petrochenkov Make inline const work in range patterns Fixes rust-lang#78108 which is a follow up of rust-lang#77124 r? @petrochenkov
…t, r=petrochenkov Make inline const work in range patterns Fixes rust-lang#78108 which is a follow up of rust-lang#77124 r? @petrochenkov
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
cc @ecstatic-morse @lcnr @oli-obk @petrochenkov