diff options
| author | Nicholas Nethercote <n.nethercote@gmail.com> | 2024-09-24 15:24:26 +1000 |
|---|---|---|
| committer | Nicholas Nethercote <n.nethercote@gmail.com> | 2025-03-07 14:51:08 +1100 |
| commit | 3378ee1a4f2ddfc4b740b70d286fc32d81aca005 (patch) | |
| tree | 2d4574374e0494aac883372d85d2b87f43e37704 | |
| parent | 293fe0a9667b442b2a4adf94bbf68bf60391441c (diff) | |
| download | rust-3378ee1a4f2ddfc4b740b70d286fc32d81aca005.tar.gz rust-3378ee1a4f2ddfc4b740b70d286fc32d81aca005.zip | |
More denesting of invisibly-delimited groups.
This time when converting them to proc-macro `Group` form.
| -rw-r--r-- | compiler/rustc_expand/src/proc_macro_server.rs | 20 | ||||
| -rw-r--r-- | tests/ui/proc-macro/nodelim-groups.rs | 13 | ||||
| -rw-r--r-- | tests/ui/proc-macro/nodelim-groups.stdout | 15 |
3 files changed, 47 insertions, 1 deletions
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 7e5e02fd41b..e0269eb6903 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -115,7 +115,7 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre while let Some(tree) = iter.next() { let (Token { kind, span }, joint) = match tree.clone() { - tokenstream::TokenTree::Delimited(span, _, delim, stream) => { + tokenstream::TokenTree::Delimited(span, _, mut delim, mut stream) => { // We used to have an alternative behaviour for crates that // needed it: a hack used to pass AST fragments to // attribute and derive macros as a single nonterminal @@ -131,6 +131,24 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre rustc.psess(), ); } + + // In `mk_delimited` we avoid nesting invisible delimited + // of the same `MetaVarKind`. Here we do the same but + // ignore the `MetaVarKind` because it is discarded when we + // convert it to a `Group`. + while let Delimiter::Invisible(InvisibleOrigin::MetaVar(_)) = delim { + if stream.len() == 1 + && let tree = stream.iter().next().unwrap() + && let tokenstream::TokenTree::Delimited(_, _, delim2, stream2) = tree + && let Delimiter::Invisible(InvisibleOrigin::MetaVar(_)) = delim2 + { + delim = *delim2; + stream = stream2.clone(); + } else { + break; + } + } + trees.push(TokenTree::Group(Group { delimiter: pm::Delimiter::from_internal(delim), stream: Some(stream), diff --git a/tests/ui/proc-macro/nodelim-groups.rs b/tests/ui/proc-macro/nodelim-groups.rs index 9acdc7023c0..8b0324214b9 100644 --- a/tests/ui/proc-macro/nodelim-groups.rs +++ b/tests/ui/proc-macro/nodelim-groups.rs @@ -19,4 +19,17 @@ macro_rules! expand_it { fn main() { expand_it!(1 + (25) + 1); expand_it!(("hello".len()) ("world".len())); + f(); +} + +// The key thing here is to produce a single `None`-delimited `Group`, even +// though there is multiple levels of macros. +macro_rules! m5 { ($e:expr) => { print_bang_consume!($e) }; } +macro_rules! m4 { ($e:expr) => { m5!($e); } } +macro_rules! m3 { ($e:expr) => { m4!($e); } } +macro_rules! m2 { ($e:expr) => { m3!($e); } } +macro_rules! m1 { ($e:expr) => { m2!($e); } } + +fn f() { + m1!(123); } diff --git a/tests/ui/proc-macro/nodelim-groups.stdout b/tests/ui/proc-macro/nodelim-groups.stdout index cdf851b535a..61001035c26 100644 --- a/tests/ui/proc-macro/nodelim-groups.stdout +++ b/tests/ui/proc-macro/nodelim-groups.stdout @@ -165,3 +165,18 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ span: $DIR/nodelim-groups.rs:16:52: 16:59 (#8), }, ] +PRINT-BANG INPUT (DISPLAY): 123 +PRINT-BANG INPUT (DEBUG): TokenStream [ + Group { + delimiter: None, + stream: TokenStream [ + Literal { + kind: Integer, + symbol: "123", + suffix: None, + span: $DIR/nodelim-groups.rs:34:9: 34:12 (#0), + }, + ], + span: $DIR/nodelim-groups.rs:27:54: 27:56 (#16), + }, +] |
