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

`}

`