From 0f793cc405700acc36c19576a36d3fe0ed00b491 Mon Sep 17 00:00:00 2001 From: delta17920 Date: Mon, 15 Dec 2025 15:28:57 +0000 Subject: [PATCH] Fix macro_metavar_expr_concat behavior with nested repetitions --- compiler/rustc_expand/src/mbe/transcribe.rs | 29 ++++++++------- tests/ui/macros/concat-nested-repetition.rs | 35 +++++++++++++++++++ .../in-repetition.rs | 2 +- .../in-repetition.stderr | 6 ++-- .../metavar-expressions/concat-repetitions.rs | 7 ++-- .../concat-repetitions.stderr | 18 +++++----- 6 files changed, 67 insertions(+), 30 deletions(-) create mode 100644 tests/ui/macros/concat-nested-repetition.rs diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index dddd62a4945a2..30e7cf5e55eec 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -558,26 +558,29 @@ fn metavar_expr_concat<'tx>( MetaVarExprConcatElem::Ident(elem) => elem.name, MetaVarExprConcatElem::Literal(elem) => *elem, MetaVarExprConcatElem::Var(ident) => { - match matched_from_ident(dcx, *ident, tscx.interp)? { - NamedMatch::MatchedSeq(named_matches) => { - let Some((curr_idx, _)) = tscx.repeats.last() else { - return Err(dcx.struct_span_err(dspan.entire(), "invalid syntax")); - }; - match &named_matches[*curr_idx] { - // FIXME(c410-f3r) Nested repetitions are unimplemented - MatchedSeq(_) => { + let mut matched = matched_from_ident(dcx, *ident, tscx.interp)?; + let mut repeats_iter = tscx.repeats.iter(); + + loop { + match matched { + NamedMatch::MatchedSingle(pnr) => { + let symbol = extract_symbol_from_pnr(dcx, pnr, ident.span)?; + concatenated.push_str(symbol.as_str()); + break; + } + NamedMatch::MatchedSeq(named_matches) => { + if let Some((idx, _)) = repeats_iter.next() { + matched = &named_matches[*idx]; + } else { return Err(dcx.struct_span_err( ident.span, - "nested repetitions with `${concat(...)}` metavariable expressions are not yet supported", + "`${concat(...)}` variable is still repeating at this depth", )); } - MatchedSingle(pnr) => extract_symbol_from_pnr(dcx, pnr, ident.span)?, } } - NamedMatch::MatchedSingle(pnr) => { - extract_symbol_from_pnr(dcx, pnr, ident.span)? - } } + continue; } }; concatenated.push_str(symbol.as_str()); diff --git a/tests/ui/macros/concat-nested-repetition.rs b/tests/ui/macros/concat-nested-repetition.rs new file mode 100644 index 0000000000000..ac5394ef8dcc3 --- /dev/null +++ b/tests/ui/macros/concat-nested-repetition.rs @@ -0,0 +1,35 @@ +//@ check-pass +#![feature(macro_metavar_expr_concat)] + +struct A; +struct B; +const AA: A = A; +const BB: B = B; + +macro_rules! define_ioctl_data { + (struct $s:ident { + $($field:ident: $ty:ident $([$opt:ident])?,)* + }) => { + pub struct $s { + $($field: $ty,)* + } + + impl $s { + $($( + fn ${concat(get_, $field)}(&self) -> $ty { + let _ = $opt; + todo!() + } + )?)* + } + }; +} + +define_ioctl_data! { + struct Foo { + a: A [AA], + b: B [BB], + } +} + +fn main() {} diff --git a/tests/ui/macros/macro-metavar-expr-concat/in-repetition.rs b/tests/ui/macros/macro-metavar-expr-concat/in-repetition.rs index d2bd31b06d606..3ee11d373e054 100644 --- a/tests/ui/macros/macro-metavar-expr-concat/in-repetition.rs +++ b/tests/ui/macros/macro-metavar-expr-concat/in-repetition.rs @@ -11,7 +11,7 @@ macro_rules! InRepetition { ) => { $( $( - ${concat(_, $arg)} //~ ERROR nested repetitions with `${concat(...)}` metavariable expressions are not yet supported + ${concat(_, $arg)} //~ ERROR macro expansion ends with an incomplete expression: expected one of `!` or `::` )* )* }; diff --git a/tests/ui/macros/macro-metavar-expr-concat/in-repetition.stderr b/tests/ui/macros/macro-metavar-expr-concat/in-repetition.stderr index ec39ca799e198..b84d98874931e 100644 --- a/tests/ui/macros/macro-metavar-expr-concat/in-repetition.stderr +++ b/tests/ui/macros/macro-metavar-expr-concat/in-repetition.stderr @@ -1,8 +1,8 @@ -error: nested repetitions with `${concat(...)}` metavariable expressions are not yet supported - --> $DIR/in-repetition.rs:14:30 +error: macro expansion ends with an incomplete expression: expected one of `!` or `::` + --> $DIR/in-repetition.rs:14:35 | LL | ${concat(_, $arg)} - | ^^^ + | ^ expected one of `!` or `::` error: aborting due to 1 previous error diff --git a/tests/ui/macros/metavar-expressions/concat-repetitions.rs b/tests/ui/macros/metavar-expressions/concat-repetitions.rs index 52a7d5cd8a7e6..133a969b1248b 100644 --- a/tests/ui/macros/metavar-expressions/concat-repetitions.rs +++ b/tests/ui/macros/metavar-expressions/concat-repetitions.rs @@ -11,8 +11,7 @@ macro_rules! one_rep { macro_rules! issue_128346 { ( $($a:ident)* ) => { A( - const ${concat($a, Z)}: i32 = 3; - //~^ ERROR invalid syntax + const ${concat($a, Z)}: i32 = 3; //~ ERROR `${concat(...)}` variable is still repeating at this depth )* }; } @@ -20,8 +19,8 @@ macro_rules! issue_128346 { macro_rules! issue_131393 { ($t:ident $($en:ident)?) => { read::<${concat($t, $en)}>() - //~^ ERROR invalid syntax - //~| ERROR invalid syntax + //~^ ERROR `${concat(...)}` variable is still repeating at this depth + //~| ERROR `${concat(...)}` variable is still repeating at this depth } } diff --git a/tests/ui/macros/metavar-expressions/concat-repetitions.stderr b/tests/ui/macros/metavar-expressions/concat-repetitions.stderr index 18b0a90c1c8a7..0ef20c65a2843 100644 --- a/tests/ui/macros/metavar-expressions/concat-repetitions.stderr +++ b/tests/ui/macros/metavar-expressions/concat-repetitions.stderr @@ -1,20 +1,20 @@ -error: invalid syntax - --> $DIR/concat-repetitions.rs:14:20 +error: `${concat(...)}` variable is still repeating at this depth + --> $DIR/concat-repetitions.rs:14:29 | LL | const ${concat($a, Z)}: i32 = 3; - | ^^^^^^^^^^^^^^^ + | ^ -error: invalid syntax - --> $DIR/concat-repetitions.rs:22:17 +error: `${concat(...)}` variable is still repeating at this depth + --> $DIR/concat-repetitions.rs:21:30 | LL | read::<${concat($t, $en)}>() - | ^^^^^^^^^^^^^^^^^ + | ^^ -error: invalid syntax - --> $DIR/concat-repetitions.rs:22:17 +error: `${concat(...)}` variable is still repeating at this depth + --> $DIR/concat-repetitions.rs:21:30 | LL | read::<${concat($t, $en)}>() - | ^^^^^^^^^^^^^^^^^ + | ^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`