7373pub ( crate ) use NamedMatch :: * ;
7474pub ( crate ) use ParseResult :: * ;
7575
76- use crate :: mbe:: { KleeneOp , TokenTree } ;
76+ use crate :: mbe:: { macro_rules :: Tracker , KleeneOp , TokenTree } ;
7777
7878use rustc_ast:: token:: { self , DocComment , Nonterminal , NonterminalKind , Token } ;
79+ use rustc_data_structures:: fx:: FxHashMap ;
80+ use rustc_data_structures:: sync:: Lrc ;
81+ use rustc_errors:: ErrorGuaranteed ;
7982use rustc_lint_defs:: pluralize;
8083use rustc_parse:: parser:: { NtOrTt , Parser } ;
84+ use rustc_span:: symbol:: Ident ;
8185use rustc_span:: symbol:: MacroRulesNormalizedIdent ;
8286use rustc_span:: Span ;
83-
84- use rustc_data_structures:: fx:: FxHashMap ;
85- use rustc_data_structures:: sync:: Lrc ;
86- use rustc_span:: symbol:: Ident ;
8787use std:: borrow:: Cow ;
8888use std:: collections:: hash_map:: Entry :: { Occupied , Vacant } ;
8989
@@ -96,7 +96,8 @@ use std::collections::hash_map::Entry::{Occupied, Vacant};
9696///
9797/// This means a matcher can be represented by `&[MatcherLoc]`, and traversal mostly involves
9898/// simply incrementing the current matcher position index by one.
99- pub ( super ) enum MatcherLoc {
99+ #[ derive( Debug ) ]
100+ pub ( crate ) enum MatcherLoc {
100101 Token {
101102 token : Token ,
102103 } ,
@@ -270,13 +271,17 @@ pub(crate) enum ParseResult<T> {
270271 Failure ( Token , & ' static str ) ,
271272 /// Fatal error (malformed macro?). Abort compilation.
272273 Error ( rustc_span:: Span , String ) ,
273- ErrorReported ,
274+ ErrorReported ( ErrorGuaranteed ) ,
274275}
275276
276277/// A `ParseResult` where the `Success` variant contains a mapping of
277278/// `MacroRulesNormalizedIdent`s to `NamedMatch`es. This represents the mapping
278279/// of metavars to the token trees they bind to.
279- pub ( crate ) type NamedParseResult = ParseResult < FxHashMap < MacroRulesNormalizedIdent , NamedMatch > > ;
280+ pub ( crate ) type NamedParseResult = ParseResult < NamedMatches > ;
281+
282+ /// Contains a mapping of `MacroRulesNormalizedIdent`s to `NamedMatch`es.
283+ /// This represents the mapping of metavars to the token trees they bind to.
284+ pub ( crate ) type NamedMatches = FxHashMap < MacroRulesNormalizedIdent , NamedMatch > ;
280285
281286/// Count how many metavars declarations are in `matcher`.
282287pub ( super ) fn count_metavar_decls ( matcher : & [ TokenTree ] ) -> usize {
@@ -400,17 +405,21 @@ impl TtParser {
400405 ///
401406 /// `Some(result)` if everything is finished, `None` otherwise. Note that matches are kept
402407 /// track of through the mps generated.
403- fn parse_tt_inner (
408+ fn parse_tt_inner < ' matcher , T : Tracker < ' matcher > > (
404409 & mut self ,
405- matcher : & [ MatcherLoc ] ,
410+ matcher : & ' matcher [ MatcherLoc ] ,
406411 token : & Token ,
412+ track : & mut T ,
407413 ) -> Option < NamedParseResult > {
408414 // Matcher positions that would be valid if the macro invocation was over now. Only
409415 // modified if `token == Eof`.
410416 let mut eof_mps = EofMatcherPositions :: None ;
411417
412418 while let Some ( mut mp) = self . cur_mps . pop ( ) {
413- match & matcher[ mp. idx ] {
419+ let matcher_loc = & matcher[ mp. idx ] ;
420+ track. before_match_loc ( self , matcher_loc) ;
421+
422+ match matcher_loc {
414423 MatcherLoc :: Token { token : t } => {
415424 // If it's a doc comment, we just ignore it and move on to the next tt in the
416425 // matcher. This is a bug, but #95267 showed that existing programs rely on
@@ -450,7 +459,7 @@ impl TtParser {
450459 // Try zero matches of this sequence, by skipping over it.
451460 self . cur_mps . push ( MatcherPos {
452461 idx : idx_first_after,
453- matches : mp. matches . clone ( ) , // a cheap clone
462+ matches : Lrc :: clone ( & mp. matches ) ,
454463 } ) ;
455464 }
456465
@@ -463,8 +472,8 @@ impl TtParser {
463472 // sequence. If that's not possible, `ending_mp` will fail quietly when it is
464473 // processed next time around the loop.
465474 let ending_mp = MatcherPos {
466- idx : mp. idx + 1 , // +1 skips the Kleene op
467- matches : mp. matches . clone ( ) , // a cheap clone
475+ idx : mp. idx + 1 , // +1 skips the Kleene op
476+ matches : Lrc :: clone ( & mp. matches ) ,
468477 } ;
469478 self . cur_mps . push ( ending_mp) ;
470479
@@ -479,8 +488,8 @@ impl TtParser {
479488 // separator yet. Try ending the sequence. If that's not possible, `ending_mp`
480489 // will fail quietly when it is processed next time around the loop.
481490 let ending_mp = MatcherPos {
482- idx : mp. idx + 2 , // +2 skips the separator and the Kleene op
483- matches : mp. matches . clone ( ) , // a cheap clone
491+ idx : mp. idx + 2 , // +2 skips the separator and the Kleene op
492+ matches : Lrc :: clone ( & mp. matches ) ,
484493 } ;
485494 self . cur_mps . push ( ending_mp) ;
486495
@@ -552,10 +561,11 @@ impl TtParser {
552561 }
553562
554563 /// Match the token stream from `parser` against `matcher`.
555- pub ( super ) fn parse_tt (
564+ pub ( super ) fn parse_tt < ' matcher , T : Tracker < ' matcher > > (
556565 & mut self ,
557566 parser : & mut Cow < ' _ , Parser < ' _ > > ,
558- matcher : & [ MatcherLoc ] ,
567+ matcher : & ' matcher [ MatcherLoc ] ,
568+ track : & mut T ,
559569 ) -> NamedParseResult {
560570 // A queue of possible matcher positions. We initialize it with the matcher position in
561571 // which the "dot" is before the first token of the first token tree in `matcher`.
@@ -571,7 +581,8 @@ impl TtParser {
571581
572582 // Process `cur_mps` until either we have finished the input or we need to get some
573583 // parsing from the black-box parser done.
574- if let Some ( res) = self . parse_tt_inner ( matcher, & parser. token ) {
584+ let res = self . parse_tt_inner ( matcher, & parser. token , track) ;
585+ if let Some ( res) = res {
575586 return res;
576587 }
577588
@@ -612,14 +623,14 @@ impl TtParser {
612623 // edition-specific matching behavior for non-terminals.
613624 let nt = match parser. to_mut ( ) . parse_nonterminal ( kind) {
614625 Err ( mut err) => {
615- err. span_label (
626+ let guarantee = err. span_label (
616627 span,
617628 format ! (
618629 "while parsing argument for this `{kind}` macro fragment"
619630 ) ,
620631 )
621632 . emit ( ) ;
622- return ErrorReported ;
633+ return ErrorReported ( guarantee ) ;
623634 }
624635 Ok ( nt) => nt,
625636 } ;
0 commit comments