Allow concat in repetitions · rust-lang/rust@b8d4e4d (original) (raw)
`@@ -557,17 +557,13 @@ fn lockstep_iter_size(
`
557
557
`}
`
558
558
`}
`
559
559
`TokenTree::MetaVarExpr(_, expr) => {
`
560
``
`-
let default_rslt = LockstepIterSize::Unconstrained;
`
561
``
`-
let Some(ident) = expr.ident() else {
`
562
``
`-
return default_rslt;
`
563
``
`-
};
`
564
``
`-
let name = MacroRulesNormalizedIdent::new(ident);
`
565
``
`-
match lookup_cur_matched(name, interpolations, repeats) {
`
566
``
`-
Some(MatchedSeq(ads)) => {
`
567
``
`-
default_rslt.with(LockstepIterSize::Constraint(ads.len(), name))
`
568
``
`-
}
`
569
``
`-
_ => default_rslt,
`
570
``
`-
}
`
``
560
`+
expr.for_each_metavar(LockstepIterSize::Unconstrained, |lis, ident| {
`
``
561
`+
lis.with(lockstep_iter_size(
`
``
562
`+
&TokenTree::MetaVar(ident.span, *ident),
`
``
563
`+
interpolations,
`
``
564
`+
repeats,
`
``
565
`+
))
`
``
566
`+
})
`
571
567
`}
`
572
568
`TokenTree::Token(..) => LockstepIterSize::Unconstrained,
`
573
569
`}
`
`@@ -695,7 +691,23 @@ fn transcribe_metavar_expr<'a>(
`
695
691
`let symbol = match element {
`
696
692
`MetaVarExprConcatElem::Ident(elem) => elem.name,
`
697
693
`MetaVarExprConcatElem::Literal(elem) => *elem,
`
698
``
`-
MetaVarExprConcatElem::Var(elem) => extract_var_symbol(dcx, *elem, interp)?,
`
``
694
`+
MetaVarExprConcatElem::Var(ident) => {
`
``
695
`+
match matched_from_ident(dcx, *ident, interp)? {
`
``
696
`+
NamedMatch::MatchedSeq(named_matches) => {
`
``
697
`+
let curr_idx = repeats.last().unwrap().0;
`
``
698
`+
match &named_matches[curr_idx] {
`
``
699
`+
// FIXME(c410-f3r) Nested repetitions are unimplemented
`
``
700
`+
MatchedSeq(_) => unimplemented!(),
`
``
701
`+
MatchedSingle(pnr) => {
`
``
702
`+
extract_symbol_from_pnr(dcx, pnr, ident.span)?
`
``
703
`+
}
`
``
704
`+
}
`
``
705
`+
}
`
``
706
`+
NamedMatch::MatchedSingle(pnr) => {
`
``
707
`+
extract_symbol_from_pnr(dcx, pnr, ident.span)?
`
``
708
`+
}
`
``
709
`+
}
`
``
710
`+
}
`
699
711
`};
`
700
712
` concatenated.push_str(symbol.as_str());
`
701
713
`}
`
`@@ -752,41 +764,48 @@ fn transcribe_metavar_expr<'a>(
`
752
764
`}
`
753
765
``
754
766
`/// Extracts an metavariable symbol that can be an identifier, a token tree or a literal.
`
755
``
`-
fn extract_var_symbol<'a>(
`
``
767
`+
fn extract_symbol_from_pnr<'a>(
`
756
768
`dcx: DiagCtxtHandle<'a>,
`
757
``
`-
ident: Ident,
`
758
``
`-
interp: &FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
`
``
769
`+
pnr: &ParseNtResult,
`
``
770
`+
span_err: Span,
`
759
771
`) -> PResult<'a, Symbol> {
`
760
``
`-
if let NamedMatch::MatchedSingle(pnr) = matched_from_ident(dcx, ident, interp)? {
`
761
``
`-
if let ParseNtResult::Ident(nt_ident, is_raw) = pnr {
`
``
772
`+
match pnr {
`
``
773
`+
ParseNtResult::Ident(nt_ident, is_raw) => {
`
762
774
`if let IdentIsRaw::Yes = is_raw {
`
763
``
`-
return Err(dcx.struct_span_err(ident.span, RAW_IDENT_ERR));
`
``
775
`+
return Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR));
`
764
776
`}
`
765
777
`return Ok(nt_ident.name);
`
766
778
`}
`
767
``
-
768
``
`-
if let ParseNtResult::Tt(TokenTree::Token(Token { kind, .. }, _)) = pnr {
`
769
``
`-
if let TokenKind::Ident(symbol, is_raw) = kind {
`
770
``
`-
if let IdentIsRaw::Yes = is_raw {
`
771
``
`-
return Err(dcx.struct_span_err(ident.span, RAW_IDENT_ERR));
`
772
``
`-
}
`
773
``
`-
return Ok(*symbol);
`
774
``
`-
}
`
775
``
-
776
``
`-
if let TokenKind::Literal(Lit { kind: LitKind::Str, symbol, suffix: None }) = kind {
`
777
``
`-
return Ok(*symbol);
`
``
779
`+
ParseNtResult::Tt(TokenTree::Token(
`
``
780
`+
Token { kind: TokenKind::Ident(symbol, is_raw), .. },
`
``
781
`+
_,
`
``
782
`+
)) => {
`
``
783
`+
if let IdentIsRaw::Yes = is_raw {
`
``
784
`+
return Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR));
`
778
785
`}
`
``
786
`+
return Ok(*symbol);
`
779
787
`}
`
780
``
-
781
``
`-
if let ParseNtResult::Nt(nt) = pnr
`
782
``
`-
&& let Nonterminal::NtLiteral(expr) = &**nt
`
783
``
`-
&& let ExprKind::Lit(Lit { kind: LitKind::Str, symbol, suffix: None }) = &expr.kind
`
``
788
`+
ParseNtResult::Tt(TokenTree::Token(
`
``
789
`+
Token {
`
``
790
`+
kind: TokenKind::Literal(Lit { kind: LitKind::Str, symbol, suffix: None }),
`
``
791
`+
..
`
``
792
`+
},
`
``
793
`+
_,
`
``
794
`+
)) => {
`
``
795
`+
return Ok(*symbol);
`
``
796
`+
}
`
``
797
`+
ParseNtResult::Nt(nt)
`
``
798
`+
if let Nonterminal::NtLiteral(expr) = &**nt
`
``
799
`+
&& let ExprKind::Lit(Lit { kind: LitKind::Str, symbol, suffix: None }) =
`
``
800
`+
&expr.kind =>
`
784
801
`{
`
785
802
`return Ok(*symbol);
`
786
803
`}
`
``
804
`+
_ => Err(dcx
`
``
805
`+
.struct_err(
`
``
806
`` +
"metavariables of ${concat(..)}
must be of type ident
, literal
or tt
",
``
``
807
`+
)
`
``
808
`+
.with_note("currently only string literals are supported")
`
``
809
`+
.with_span(span_err)),
`
787
810
`}
`
788
``
`-
Err(dcx
`
789
``
`` -
.struct_err("metavariables of ${concat(..)}
must be of type ident
, literal
or tt
")
``
790
``
`-
.with_note("currently only string literals are supported")
`
791
``
`-
.with_span(ident.span))
`
792
811
`}
`