-
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
Accept m!{ .. }.method()
and m!{ .. }?
statements.
#88690
Accept m!{ .. }.method()
and m!{ .. }?
statements.
#88690
Conversation
r? @nagisa (rust-highfive has picked a reviewer for you, use r? to override) |
m!{ .. }.method()
and m!{ .. }?
statements.
@rust-lang/lang I suppose this requires an FCP? |
I think, before approving something like this, we'd want to know if this restriction is important for any particular reason (e.g. interactions with parsing and follow sets). I don't think it would be, given the examples you gave, but it'd be helpful to have some guidance from someone with clear knowledge of how macros interact with the parser. For my part, assuming it wouldn't break anything, I think this seems reasonable. |
I think this is the right thing to do and don't see any reasons for braced macros cc @Aaron1011 just in case |
+1 from me, I agree that this seems more consistent. |
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'm okay with this change on the implementation side of things.
On the language design side of things I feel like with this adjustment we end up neither here nor there for this syntax element appears to be treated in a fairly inconsistent manner compared to the rest of Rust's syntactic constructs. That is it now acts kind of like an expression but only in very specific contexts. I think it would be a good idea to go all the way to making it act like all the other ExpressionWithBlock
s.
+1 from me as well for making it consistent. Given that things like let x = loop { break 7_u32 }.count_ones(); work, then those same things working after macro_rules with braces seems like the right choice. |
r=me with a negative test added. At this point a FCP seems redundant given that we already had +1 from 3/5 T-lang members. |
@bors r= nagisa |
📌 Commit 7d8d7a0 has been approved by `` |
📌 Commit 7d8d7a0 has been approved by |
…xpr-parse, r=nagisa Accept `m!{ .. }.method()` and `m!{ .. }?` statements. This PR fixes something that I keep running into when using `quote!{}.into()` in a proc macro to convert the `proc_macro2::TokenStream` to a `proc_macro::TokenStream`: Before: ``` error: expected expression, found `.` --> src/lib.rs:6:6 | 4 | quote! { 5 | ... 6 | }.into() | ^ expected expression ``` After: ``` ``` (No output, compiles fine.) --- Context: For expressions like `{ 1 }` and `if true { 1 } else { 2 }`, we accept them as full statements without a trailing `;`, which means the following is not accepted: ```rust { 1 } - 1 // error ``` since that is parsed as two statements: `{ 1 }` and `-1`. Syntactically correct, but the type of `{ 1 }` should be `()` as there is no `;`. However, for specifically `.` and `?` after the `}`, we do [continue parsing it as an expression](https://github.com/rust-lang/rust/blob/13db8440bbbe42870bc828d4ec3e965b38670277/compiler/rustc_parse/src/parser/expr.rs#L864-L876): ```rust { "abc" }.len(); // ok ``` For braced macro invocations, we do not do this: ```rust vec![1, 2, 3].len(); // ok vec!{1, 2, 3}.len(); // error ``` (It parses `vec!{1, 2, 3}` as a full statement, and then complains about `.len()` not being a valid expression.) This PR changes this to also look for a `.` and `?` after a braced macro invocation. We can be sure the macro is an expression and not a full statement in those cases, since no statement can start with a `.` or `?`.
…xpr-parse, r=nagisa Accept `m!{ .. }.method()` and `m!{ .. }?` statements. This PR fixes something that I keep running into when using `quote!{}.into()` in a proc macro to convert the `proc_macro2::TokenStream` to a `proc_macro::TokenStream`: Before: ``` error: expected expression, found `.` --> src/lib.rs:6:6 | 4 | quote! { 5 | ... 6 | }.into() | ^ expected expression ``` After: ``` ``` (No output, compiles fine.) --- Context: For expressions like `{ 1 }` and `if true { 1 } else { 2 }`, we accept them as full statements without a trailing `;`, which means the following is not accepted: ```rust { 1 } - 1 // error ``` since that is parsed as two statements: `{ 1 }` and `-1`. Syntactically correct, but the type of `{ 1 }` should be `()` as there is no `;`. However, for specifically `.` and `?` after the `}`, we do [continue parsing it as an expression](https://github.com/rust-lang/rust/blob/13db8440bbbe42870bc828d4ec3e965b38670277/compiler/rustc_parse/src/parser/expr.rs#L864-L876): ```rust { "abc" }.len(); // ok ``` For braced macro invocations, we do not do this: ```rust vec![1, 2, 3].len(); // ok vec!{1, 2, 3}.len(); // error ``` (It parses `vec!{1, 2, 3}` as a full statement, and then complains about `.len()` not being a valid expression.) This PR changes this to also look for a `.` and `?` after a braced macro invocation. We can be sure the macro is an expression and not a full statement in those cases, since no statement can start with a `.` or `?`.
…xpr-parse, r=nagisa Accept `m!{ .. }.method()` and `m!{ .. }?` statements. This PR fixes something that I keep running into when using `quote!{}.into()` in a proc macro to convert the `proc_macro2::TokenStream` to a `proc_macro::TokenStream`: Before: ``` error: expected expression, found `.` --> src/lib.rs:6:6 | 4 | quote! { 5 | ... 6 | }.into() | ^ expected expression ``` After: ``` ``` (No output, compiles fine.) --- Context: For expressions like `{ 1 }` and `if true { 1 } else { 2 }`, we accept them as full statements without a trailing `;`, which means the following is not accepted: ```rust { 1 } - 1 // error ``` since that is parsed as two statements: `{ 1 }` and `-1`. Syntactically correct, but the type of `{ 1 }` should be `()` as there is no `;`. However, for specifically `.` and `?` after the `}`, we do [continue parsing it as an expression](https://github.com/rust-lang/rust/blob/13db8440bbbe42870bc828d4ec3e965b38670277/compiler/rustc_parse/src/parser/expr.rs#L864-L876): ```rust { "abc" }.len(); // ok ``` For braced macro invocations, we do not do this: ```rust vec![1, 2, 3].len(); // ok vec!{1, 2, 3}.len(); // error ``` (It parses `vec!{1, 2, 3}` as a full statement, and then complains about `.len()` not being a valid expression.) This PR changes this to also look for a `.` and `?` after a braced macro invocation. We can be sure the macro is an expression and not a full statement in those cases, since no statement can start with a `.` or `?`.
…xpr-parse, r=nagisa Accept `m!{ .. }.method()` and `m!{ .. }?` statements. This PR fixes something that I keep running into when using `quote!{}.into()` in a proc macro to convert the `proc_macro2::TokenStream` to a `proc_macro::TokenStream`: Before: ``` error: expected expression, found `.` --> src/lib.rs:6:6 | 4 | quote! { 5 | ... 6 | }.into() | ^ expected expression ``` After: ``` ``` (No output, compiles fine.) --- Context: For expressions like `{ 1 }` and `if true { 1 } else { 2 }`, we accept them as full statements without a trailing `;`, which means the following is not accepted: ```rust { 1 } - 1 // error ``` since that is parsed as two statements: `{ 1 }` and `-1`. Syntactically correct, but the type of `{ 1 }` should be `()` as there is no `;`. However, for specifically `.` and `?` after the `}`, we do [continue parsing it as an expression](https://github.com/rust-lang/rust/blob/13db8440bbbe42870bc828d4ec3e965b38670277/compiler/rustc_parse/src/parser/expr.rs#L864-L876): ```rust { "abc" }.len(); // ok ``` For braced macro invocations, we do not do this: ```rust vec![1, 2, 3].len(); // ok vec!{1, 2, 3}.len(); // error ``` (It parses `vec!{1, 2, 3}` as a full statement, and then complains about `.len()` not being a valid expression.) This PR changes this to also look for a `.` and `?` after a braced macro invocation. We can be sure the macro is an expression and not a full statement in those cases, since no statement can start with a `.` or `?`.
…xpr-parse, r=nagisa Accept `m!{ .. }.method()` and `m!{ .. }?` statements. This PR fixes something that I keep running into when using `quote!{}.into()` in a proc macro to convert the `proc_macro2::TokenStream` to a `proc_macro::TokenStream`: Before: ``` error: expected expression, found `.` --> src/lib.rs:6:6 | 4 | quote! { 5 | ... 6 | }.into() | ^ expected expression ``` After: ``` ``` (No output, compiles fine.) --- Context: For expressions like `{ 1 }` and `if true { 1 } else { 2 }`, we accept them as full statements without a trailing `;`, which means the following is not accepted: ```rust { 1 } - 1 // error ``` since that is parsed as two statements: `{ 1 }` and `-1`. Syntactically correct, but the type of `{ 1 }` should be `()` as there is no `;`. However, for specifically `.` and `?` after the `}`, we do [continue parsing it as an expression](https://github.com/rust-lang/rust/blob/13db8440bbbe42870bc828d4ec3e965b38670277/compiler/rustc_parse/src/parser/expr.rs#L864-L876): ```rust { "abc" }.len(); // ok ``` For braced macro invocations, we do not do this: ```rust vec![1, 2, 3].len(); // ok vec!{1, 2, 3}.len(); // error ``` (It parses `vec!{1, 2, 3}` as a full statement, and then complains about `.len()` not being a valid expression.) This PR changes this to also look for a `.` and `?` after a braced macro invocation. We can be sure the macro is an expression and not a full statement in those cases, since no statement can start with a `.` or `?`.
…arth Rollup of 8 pull requests Successful merges: - rust-lang#87320 (Introduce -Z remap-cwd-prefix switch) - rust-lang#88690 (Accept `m!{ .. }.method()` and `m!{ .. }?` statements. ) - rust-lang#88775 (Revert anon union parsing) - rust-lang#88841 (feat(rustc_typeck): suggest removing bad parens in `(recv.method)()`) - rust-lang#88907 (Highlight the `const fn` if error happened because of a bound on the impl block) - rust-lang#88915 (`Wrapping<T>` has the same layout and ABI as `T`) - rust-lang#88933 (Remove implementation of `min_align_of` intrinsic) - rust-lang#88951 (Update books) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Pkgsrc changes: * Adapt a couple of patches Upstream changes: Version 1.57.0 (2021-12-02) ========================== Language -------- - [Macro attributes may follow `#[derive]` and will see the original (pre-`cfg`) input.][87220] - [Accept curly-brace macros in expressions, like `m!{ .. }.method()` and `m!{ .. }?`.][88690] - [Allow panicking in constant evaluation.][89508] Compiler -------- - [Create more accurate debuginfo for vtables.][89597] - [Add `armv6k-nintendo-3ds` at Tier 3\*.][88529] - [Add `armv7-unknown-linux-uclibceabihf` at Tier 3\*.][88952] - [Add `m68k-unknown-linux-gnu` at Tier 3\*.][88321] - [Add SOLID targets at Tier 3\*:][86191] `aarch64-kmc-solid_asp3`, `armv7a-kmc-solid_asp3-eabi`, `armv7a-kmc-solid_asp3-eabihf` \* Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. Libraries --------- - [Avoid allocations and copying in `Vec::leak`][89337] - [Add `#[repr(i8)]` to `Ordering`][89507] - [Optimize `File::read_to_end` and `read_to_string`][89582] - [Update to Unicode 14.0][89614] - [Many more functions are marked `#[must_use]`][89692], producing a warning when ignoring their return value. This helps catch mistakes such as expecting a function to mutate a value in place rather than return a new value. Stabilised APIs --------------- - [`[T; N]::as_mut_slice`][`array::as_mut_slice`] - [`[T; N]::as_slice`][`array::as_slice`] - [`collections::TryReserveError`] - [`HashMap::try_reserve`] - [`HashSet::try_reserve`] - [`String::try_reserve`] - [`String::try_reserve_exact`] - [`Vec::try_reserve`] - [`Vec::try_reserve_exact`] - [`VecDeque::try_reserve`] - [`VecDeque::try_reserve_exact`] - [`Iterator::map_while`] - [`iter::MapWhile`] - [`proc_macro::is_available`] - [`Command::get_program`] - [`Command::get_args`] - [`Command::get_envs`] - [`Command::get_current_dir`] - [`CommandArgs`] - [`CommandEnvs`] These APIs are now usable in const contexts: - [`hint::unreachable_unchecked`] Cargo ----- - [Stabilize custom profiles][cargo/9943] Compatibility notes ------------------- Internal changes ---------------- These changes provide no direct user facing benefits, but represent significant improvements to the internals and overall performance of rustc and related tools. - [Added an experimental backend for codegen with `libgccjit`.][87260] [86191]: rust-lang/rust#86191 [87220]: rust-lang/rust#87220 [87260]: rust-lang/rust#87260 [88243]: rust-lang/rust#88243 [88321]: rust-lang/rust#88321 [88529]: rust-lang/rust#88529 [88690]: rust-lang/rust#88690 [88952]: rust-lang/rust#88952 [89337]: rust-lang/rust#89337 [89507]: rust-lang/rust#89507 [89508]: rust-lang/rust#89508 [89582]: rust-lang/rust#89582 [89597]: rust-lang/rust#89597 [89614]: rust-lang/rust#89614 [89692]: rust-lang/rust#89692 [cargo/9943]: rust-lang/cargo#9943 [`array::as_mut_slice`]: https://doc.rust-lang.org/std/primitive.array.html#method.as_mut_slice [`array::as_slice`]: https://doc.rust-lang.org/std/primitive.array.html#method.as_slice [`collections::TryReserveError`]: https://doc.rust-lang.org/std/collections/struct.TryReserveError.html [`HashMap::try_reserve`]: https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.try_reserve [`HashSet::try_reserve`]: https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.try_reserve [`String::try_reserve`]: https://doc.rust-lang.org/alloc/string/struct.String.html#method.try_reserve [`String::try_reserve_exact`]: https://doc.rust-lang.org/alloc/string/struct.String.html#method.try_reserve_exact [`Vec::try_reserve`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.try_reserve [`Vec::try_reserve_exact`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.try_reserve_exact [`VecDeque::try_reserve`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.try_reserve [`VecDeque::try_reserve_exact`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.try_reserve_exact [`Iterator::map_while`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map_while [`iter::MapWhile`]: https://doc.rust-lang.org/std/iter/struct.MapWhile.html [`proc_macro::is_available`]: https://doc.rust-lang.org/proc_macro/fn.is_available.html [`Command::get_program`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_program [`Command::get_args`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_args [`Command::get_envs`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_envs [`Command::get_current_dir`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_current_dir [`CommandArgs`]: https://doc.rust-lang.org/std/process/struct.CommandArgs.html [`CommandEnvs`]: https://doc.rust-lang.org/std/process/struct.CommandEnvs.html
Pkgsrc changes: * Adjust line numbers in a number of patches * remove the --disable-dist-src option, so that we produce the rust-src rust component, which we upload to LOCALSRC to allow the rust-src package to build, which is needed for rust-analyzer. * Cargo checksum for vendor/cc no longer needs patching; checksum for vendor/libc updated Upstream changes: Version 1.57.0 (2021-12-02) ========================== Language -------- - [Macro attributes may follow `#[derive]` and will see the original (pre-`cfg`) input.][87220] - [Accept curly-brace macros in expressions, like `m!{ .. }.method()` and `m!{ .. }?`.][88690] - [Allow panicking in constant evaluation.][89508] Compiler -------- - [Create more accurate debuginfo for vtables.][89597] - [Add `armv6k-nintendo-3ds` at Tier 3\*.][88529] - [Add `armv7-unknown-linux-uclibceabihf` at Tier 3\*.][88952] - [Add `m68k-unknown-linux-gnu` at Tier 3\*.][88321] - [Add SOLID targets at Tier 3\*:][86191] `aarch64-kmc-solid_asp3`, `armv7a-kmc-solid_asp3-eabi`, `armv7a-kmc-solid_asp3-eabihf` \* Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. Libraries --------- - [Avoid allocations and copying in `Vec::leak`][89337] - [Add `#[repr(i8)]` to `Ordering`][89507] - [Optimize `File::read_to_end` and `read_to_string`][89582] - [Update to Unicode 14.0][89614] - [Many more functions are marked `#[must_use]`][89692], producing a warning when ignoring their return value. This helps catch mistakes such as expecting a function to mutate a value in place rather than return a new value. Stabilised APIs --------------- - [`[T; N]::as_mut_slice`][`array::as_mut_slice`] - [`[T; N]::as_slice`][`array::as_slice`] - [`collections::TryReserveError`] - [`HashMap::try_reserve`] - [`HashSet::try_reserve`] - [`String::try_reserve`] - [`String::try_reserve_exact`] - [`Vec::try_reserve`] - [`Vec::try_reserve_exact`] - [`VecDeque::try_reserve`] - [`VecDeque::try_reserve_exact`] - [`Iterator::map_while`] - [`iter::MapWhile`] - [`proc_macro::is_available`] - [`Command::get_program`] - [`Command::get_args`] - [`Command::get_envs`] - [`Command::get_current_dir`] - [`CommandArgs`] - [`CommandEnvs`] These APIs are now usable in const contexts: - [`hint::unreachable_unchecked`] Cargo ----- - [Stabilize custom profiles][cargo/9943] Compatibility notes ------------------- Internal changes ---------------- These changes provide no direct user facing benefits, but represent significant improvements to the internals and overall performance of rustc and related tools. - [Added an experimental backend for codegen with `libgccjit`.][87260] [86191]: rust-lang/rust#86191 [87220]: rust-lang/rust#87220 [87260]: rust-lang/rust#87260 [88243]: rust-lang/rust#88243 [88321]: rust-lang/rust#88321 [88529]: rust-lang/rust#88529 [88690]: rust-lang/rust#88690 [88952]: rust-lang/rust#88952 [89337]: rust-lang/rust#89337 [89507]: rust-lang/rust#89507 [89508]: rust-lang/rust#89508 [89582]: rust-lang/rust#89582 [89597]: rust-lang/rust#89597 [89614]: rust-lang/rust#89614 [89692]: rust-lang/rust#89692 [cargo/9943]: rust-lang/cargo#9943 [`array::as_mut_slice`]: https://doc.rust-lang.org/std/primitive.array.html#method.as_mut_slice [`array::as_slice`]: https://doc.rust-lang.org/std/primitive.array.html#method.as_slice [`collections::TryReserveError`]: https://doc.rust-lang.org/std/collections/struct.TryReserveError.html [`HashMap::try_reserve`]: https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.try_reserve [`HashSet::try_reserve`]: https://doc.rust-lang.org/std/collections/hash_set/struct.HashSet.html#method.try_reserve [`String::try_reserve`]: https://doc.rust-lang.org/alloc/string/struct.String.html#method.try_reserve [`String::try_reserve_exact`]: https://doc.rust-lang.org/alloc/string/struct.String.html#method.try_reserve_exact [`Vec::try_reserve`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.try_reserve [`Vec::try_reserve_exact`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.try_reserve_exact [`VecDeque::try_reserve`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.try_reserve [`VecDeque::try_reserve_exact`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.try_reserve_exact [`Iterator::map_while`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map_while [`iter::MapWhile`]: https://doc.rust-lang.org/std/iter/struct.MapWhile.html [`proc_macro::is_available`]: https://doc.rust-lang.org/proc_macro/fn.is_available.html [`Command::get_program`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_program [`Command::get_args`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_args [`Command::get_envs`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_envs [`Command::get_current_dir`]: https://doc.rust-lang.org/std/process/struct.Command.html#method.get_current_dir [`CommandArgs`]: https://doc.rust-lang.org/std/process/struct.CommandArgs.html [`CommandEnvs`]: https://doc.rust-lang.org/std/process/struct.CommandEnvs.html
This PR fixes something that I keep running into when using
quote!{}.into()
in a proc macro to convert theproc_macro2::TokenStream
to aproc_macro::TokenStream
:Before:
After:
(No output, compiles fine.)
Context:
For expressions like
{ 1 }
andif true { 1 } else { 2 }
, we accept them as full statements without a trailing;
, which means the following is not accepted:since that is parsed as two statements:
{ 1 }
and-1
. Syntactically correct, but the type of{ 1 }
should be()
as there is no;
.However, for specifically
.
and?
after the}
, we do continue parsing it as an expression:For braced macro invocations, we do not do this:
(It parses
vec!{1, 2, 3}
as a full statement, and then complains about.len()
not being a valid expression.)This PR changes this to also look for a
.
and?
after a braced macro invocation. We can be sure the macro is an expression and not a full statement in those cases, since no statement can start with a.
or?
.