73
73
pub ( crate ) use NamedMatch :: * ;
74
74
pub ( crate ) use ParseResult :: * ;
75
75
76
- use crate :: mbe:: { KleeneOp , TokenTree } ;
76
+ use crate :: mbe:: { macro_rules :: Tracker , KleeneOp , TokenTree } ;
77
77
78
78
use 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 ;
79
82
use rustc_lint_defs:: pluralize;
80
83
use rustc_parse:: parser:: { NtOrTt , Parser } ;
84
+ use rustc_span:: symbol:: Ident ;
81
85
use rustc_span:: symbol:: MacroRulesNormalizedIdent ;
82
86
use rustc_span:: Span ;
83
-
84
- use rustc_data_structures:: fx:: FxHashMap ;
85
- use rustc_data_structures:: sync:: Lrc ;
86
- use rustc_span:: symbol:: Ident ;
87
87
use std:: borrow:: Cow ;
88
88
use std:: collections:: hash_map:: Entry :: { Occupied , Vacant } ;
89
89
@@ -96,7 +96,8 @@ use std::collections::hash_map::Entry::{Occupied, Vacant};
96
96
///
97
97
/// This means a matcher can be represented by `&[MatcherLoc]`, and traversal mostly involves
98
98
/// simply incrementing the current matcher position index by one.
99
- pub ( super ) enum MatcherLoc {
99
+ #[ derive( Debug ) ]
100
+ pub ( crate ) enum MatcherLoc {
100
101
Token {
101
102
token : Token ,
102
103
} ,
@@ -270,13 +271,17 @@ pub(crate) enum ParseResult<T> {
270
271
Failure ( Token , & ' static str ) ,
271
272
/// Fatal error (malformed macro?). Abort compilation.
272
273
Error ( rustc_span:: Span , String ) ,
273
- ErrorReported ,
274
+ ErrorReported ( ErrorGuaranteed ) ,
274
275
}
275
276
276
277
/// A `ParseResult` where the `Success` variant contains a mapping of
277
278
/// `MacroRulesNormalizedIdent`s to `NamedMatch`es. This represents the mapping
278
279
/// 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 > ;
280
285
281
286
/// Count how many metavars declarations are in `matcher`.
282
287
pub ( super ) fn count_metavar_decls ( matcher : & [ TokenTree ] ) -> usize {
@@ -400,17 +405,21 @@ impl TtParser {
400
405
///
401
406
/// `Some(result)` if everything is finished, `None` otherwise. Note that matches are kept
402
407
/// track of through the mps generated.
403
- fn parse_tt_inner (
408
+ fn parse_tt_inner < ' matcher , T : Tracker < ' matcher > > (
404
409
& mut self ,
405
- matcher : & [ MatcherLoc ] ,
410
+ matcher : & ' matcher [ MatcherLoc ] ,
406
411
token : & Token ,
412
+ track : & mut T ,
407
413
) -> Option < NamedParseResult > {
408
414
// Matcher positions that would be valid if the macro invocation was over now. Only
409
415
// modified if `token == Eof`.
410
416
let mut eof_mps = EofMatcherPositions :: None ;
411
417
412
418
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 {
414
423
MatcherLoc :: Token { token : t } => {
415
424
// If it's a doc comment, we just ignore it and move on to the next tt in the
416
425
// matcher. This is a bug, but #95267 showed that existing programs rely on
@@ -450,7 +459,7 @@ impl TtParser {
450
459
// Try zero matches of this sequence, by skipping over it.
451
460
self . cur_mps . push ( MatcherPos {
452
461
idx : idx_first_after,
453
- matches : mp. matches . clone ( ) , // a cheap clone
462
+ matches : Lrc :: clone ( & mp. matches ) ,
454
463
} ) ;
455
464
}
456
465
@@ -463,8 +472,8 @@ impl TtParser {
463
472
// sequence. If that's not possible, `ending_mp` will fail quietly when it is
464
473
// processed next time around the loop.
465
474
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 ) ,
468
477
} ;
469
478
self . cur_mps . push ( ending_mp) ;
470
479
@@ -479,8 +488,8 @@ impl TtParser {
479
488
// separator yet. Try ending the sequence. If that's not possible, `ending_mp`
480
489
// will fail quietly when it is processed next time around the loop.
481
490
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 ) ,
484
493
} ;
485
494
self . cur_mps . push ( ending_mp) ;
486
495
@@ -552,10 +561,11 @@ impl TtParser {
552
561
}
553
562
554
563
/// Match the token stream from `parser` against `matcher`.
555
- pub ( super ) fn parse_tt (
564
+ pub ( super ) fn parse_tt < ' matcher , T : Tracker < ' matcher > > (
556
565
& mut self ,
557
566
parser : & mut Cow < ' _ , Parser < ' _ > > ,
558
- matcher : & [ MatcherLoc ] ,
567
+ matcher : & ' matcher [ MatcherLoc ] ,
568
+ track : & mut T ,
559
569
) -> NamedParseResult {
560
570
// A queue of possible matcher positions. We initialize it with the matcher position in
561
571
// which the "dot" is before the first token of the first token tree in `matcher`.
@@ -571,7 +581,8 @@ impl TtParser {
571
581
572
582
// Process `cur_mps` until either we have finished the input or we need to get some
573
583
// 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 {
575
586
return res;
576
587
}
577
588
@@ -612,14 +623,14 @@ impl TtParser {
612
623
// edition-specific matching behavior for non-terminals.
613
624
let nt = match parser. to_mut ( ) . parse_nonterminal ( kind) {
614
625
Err ( mut err) => {
615
- err. span_label (
626
+ let guarantee = err. span_label (
616
627
span,
617
628
format ! (
618
629
"while parsing argument for this `{kind}` macro fragment"
619
630
) ,
620
631
)
621
632
. emit ( ) ;
622
- return ErrorReported ;
633
+ return ErrorReported ( guarantee ) ;
623
634
}
624
635
Ok ( nt) => nt,
625
636
} ;
0 commit comments