authorbors <bors@rust-lang.org> 2026-07-06 22:08:27 UTC
committerbors <bors@rust-lang.org> 2026-07-06 22:08:27 UTC
logb960fcf2ff0f04967b30b947be8fc155fb067901
treed5f061ec720f0f6e8cce82db0b49d7fc75b14b86
parentc4af71034e89a431eeee91125a31ad001379faac
parentc1aa8d71a6d35cfa53e80b7a0e76c0fb601ae25a

Auto merge of #158577 - bal-e:macro-parsing-polish, r=nnethercote

Polish some macro parsing code I'm working on some optimizations to `macro_parser.rs` and the surrounding code (specifically, changing the current BFS approach into a DFS), and these changes fell out during that effort. I think they make the code more accessible in addition to laying some foundations for my future work (in particular, the handling of ambiguities). This is my first proper entrance into rustc code, please let me know if I'm holding something wrong :) The commits are organized and individually reviewable. r? @nnethercote

3 files changed, 212 insertions(+), 140 deletions(-)

compiler/rustc_expand/src/mbe/diagnostics.rs+78-24
......@@ -2,9 +2,10 @@ use std::borrow::Cow;
22
33use rustc_ast::token::{self, Token};
44use rustc_ast::tokenstream::TokenStream;
5use rustc_errors::{Applicability, Diag, DiagCtxtHandle, DiagMessage};
5use rustc_errors::{Applicability, Diag, DiagCtxtHandle, DiagMessage, pluralize};
66use rustc_hir::attrs::diagnostic::{CustomDiagnostic, Directive, FormatArgs};
77use rustc_macros::Subdiagnostic;
8use rustc_middle::bug;
89use rustc_parse::parser::{Parser, Recovery, token_descr};
910use rustc_session::parse::ParseSess;
1011use rustc_span::source_map::SourceMap;
......@@ -16,7 +17,7 @@ use crate::expand::{AstFragmentKind, parse_ast_fragment};
1617use crate::mbe::macro_parser::ParseResult::*;
1718use crate::mbe::macro_parser::{MatcherLoc, NamedParseResult, TtParser};
1819use crate::mbe::macro_rules::{
19 Tracker, try_match_macro, try_match_macro_attr, try_match_macro_derive,
20 Tracker, WhichMatcher, try_match_macro, try_match_macro_attr, try_match_macro_derive,
2021};
2122
2223pub(super) enum FailedMacro<'a> {
......@@ -44,7 +45,7 @@ pub(super) fn failed_to_match_macro(
4445
4546 // An error occurred, try the expansion again, tracking the expansion closely for better
4647 // diagnostics.
47 let mut tracker = CollectTrackerAndEmitter::new(psess.dcx(), sp);
48 let mut tracker = CollectTrackerAndEmitter::new(name, psess.dcx(), sp);
4849
4950 let try_success_result = match args {
5051 FailedMacro::Func => try_match_macro(psess, name, body, rules, &mut tracker),
......@@ -121,7 +122,7 @@ pub(super) fn failed_to_match_macro(
121122 for rule in rules {
122123 let MacroRule::Func { lhs, .. } = rule else { continue };
123124 let parser = parser_from_cx(psess, body.clone(), Recovery::Allowed);
124 let mut tt_parser = TtParser::new(name);
125 let mut tt_parser = TtParser::new();
125126
126127 if let Success(_) =
127128 tt_parser.parse_tt(&mut Cow::Borrowed(&parser), lhs, &mut NoopTracker)
......@@ -145,6 +146,7 @@ pub(super) fn failed_to_match_macro(
145146
146147/// The tracker used for the slow error path that collects useful info for diagnostics.
147148struct CollectTrackerAndEmitter<'dcx, 'matcher> {
149 macro_name: Ident,
148150 dcx: DiagCtxtHandle<'dcx>,
149151 remaining_matcher: Option<&'matcher MatcherLoc>,
150152 /// Which arm's failure should we report? (the one furthest along)
......@@ -155,14 +157,22 @@ struct CollectTrackerAndEmitter<'dcx, 'matcher> {
155157
156158struct BestFailure {
157159 token: Token,
158 position_in_tokenstream: (bool, u32),
160
161 /// The matcher in which the failure occurred.
162 matcher: WhichMatcher,
163
164 /// The approximate (parser) position of the failure.
165 ///
166 /// This is relative to [`Self::matcher`].
167 position: u32,
168
159169 msg: &'static str,
160170 remaining_matcher: MatcherLoc,
161171}
162172
163173impl BestFailure {
164 fn is_better_position(&self, position: (bool, u32)) -> bool {
165 position > self.position_in_tokenstream
174 fn is_better_position(&self, matcher: WhichMatcher, position: u32) -> bool {
175 (matcher, position) > (self.matcher, self.position)
166176 }
167177}
168178
......@@ -181,8 +191,8 @@ impl<'dcx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'dcx, 'match
181191 }
182192 }
183193
184 fn after_arm(&mut self, in_body: bool, result: &NamedParseResult<Self::Failure>) {
185 match result {
194 fn after_arm(&mut self, which_matcher: WhichMatcher, result: &NamedParseResult<Self::Failure>) {
195 match *result {
186196 Success(_) => {
187197 // Nonterminal parser recovery might turn failed matches into successful ones,
188198 // but for that it must have emitted an error already
......@@ -194,15 +204,13 @@ impl<'dcx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'dcx, 'match
194204 Failure((token, approx_position, msg)) => {
195205 debug!(?token, ?msg, "a new failure of an arm");
196206
197 let position_in_tokenstream = (in_body, *approx_position);
198 if self
199 .best_failure
200 .as_ref()
201 .is_none_or(|failure| failure.is_better_position(position_in_tokenstream))
202 {
207 if self.best_failure.as_ref().is_none_or(|failure| {
208 failure.is_better_position(which_matcher, approx_position)
209 }) {
203210 self.best_failure = Some(BestFailure {
204 token: *token,
205 position_in_tokenstream,
211 token,
212 matcher: which_matcher,
213 position: approx_position,
206214 msg,
207215 remaining_matcher: self
208216 .remaining_matcher
......@@ -211,15 +219,54 @@ impl<'dcx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'dcx, 'match
211219 })
212220 }
213221 }
214 Error(err_sp, msg) => {
215 let span = err_sp.substitute_dummy(self.root_span);
216 let guar = self.dcx.span_err(span, msg.clone());
217 self.result = Some((span, guar));
222 Ambiguity => {
223 if self.result.is_none() {
224 bug!("`Error(..)` is only constructed through `Self::ambiguity()`");
225 }
218226 }
219 ErrorReported(guar) => self.result = Some((self.root_span, *guar)),
227 ErrorReported(guar) => self.result = Some((self.root_span, guar)),
220228 }
221229 }
222230
231 fn ambiguity(
232 &mut self,
233 parser: &Parser<'_>,
234 bb_locs: impl IntoIterator<Item = &'matcher MatcherLoc>,
235 next_locs: impl IntoIterator<Item = &'matcher MatcherLoc>,
236 ) {
237 let span = parser.token.span.substitute_dummy(self.root_span);
238
239 if parser.token == token::Eof {
240 let msg = "ambiguity: multiple successful parses".to_string();
241 let guar = self.dcx.span_err(span, msg);
242 self.result = Some((span, guar));
243 return;
244 }
245
246 let nts = bb_locs
247 .into_iter()
248 .map(|loc| match loc {
249 MatcherLoc::MetaVarDecl { bind, kind, .. } => {
250 format!("{kind} ('{bind}')")
251 }
252 _ => unreachable!(),
253 })
254 .collect::<Vec<String>>()
255 .join(" or ");
256
257 let msg = format!(
258 "local ambiguity when calling macro `{}`: multiple parsing options: {}",
259 self.macro_name,
260 match next_locs.into_iter().count() {
261 0 => format!("built-in NTs {nts}."),
262 n => format!("built-in NTs {nts} or {n} other option{s}.", s = pluralize!(n)),
263 }
264 );
265
266 let guar = self.dcx.span_err(span, msg);
267 self.result = Some((span, guar));
268 }
269
223270 fn description() -> &'static str {
224271 "detailed"
225272 }
......@@ -230,8 +277,15 @@ impl<'dcx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'dcx, 'match
230277}
231278
232279impl<'dcx> CollectTrackerAndEmitter<'dcx, '_> {
233 fn new(dcx: DiagCtxtHandle<'dcx>, root_span: Span) -> Self {
234 Self { dcx, remaining_matcher: None, best_failure: None, root_span, result: None }
280 fn new(macro_name: Ident, dcx: DiagCtxtHandle<'dcx>, root_span: Span) -> Self {
281 Self {
282 macro_name,
283 dcx,
284 remaining_matcher: None,
285 best_failure: None,
286 root_span,
287 result: None,
288 }
235289 }
236290}
237291
compiler/rustc_expand/src/mbe/macro_parser.rs+65-99
......@@ -71,7 +71,6 @@
7171//! ```
7272
7373use std::borrow::Cow;
74use std::collections::hash_map::Entry::{Occupied, Vacant};
7574use std::fmt::Display;
7675use std::rc::Rc;
7776
......@@ -79,10 +78,11 @@ pub(crate) use NamedMatch::*;
7978pub(crate) use ParseResult::*;
8079use rustc_ast::token::{self, DocComment, NonterminalKind, Token, TokenKind};
8180use rustc_data_structures::fx::FxHashMap;
82use rustc_errors::ErrorGuaranteed;
83use rustc_lint_defs::pluralize;
81use rustc_errors::{Diag, ErrorGuaranteed};
82use rustc_middle::span_bug;
8483use rustc_parse::parser::{ParseNtResult, Parser, token_descr};
8584use rustc_span::{Ident, MacroRulesNormalizedIdent, Span};
85use smallvec::SmallVec;
8686
8787use crate::mbe::macro_rules::Tracker;
8888use crate::mbe::{KleeneOp, TokenTree};
......@@ -292,12 +292,6 @@ impl MatcherPos {
292292 }
293293}
294294
295enum EofMatcherPositions {
296 None,
297 One(MatcherPos),
298 Multiple,
299}
300
301295/// Represents the possible results of an attempted parse.
302296#[derive(Debug)]
303297pub(crate) enum ParseResult<T, F> {
......@@ -307,8 +301,8 @@ pub(crate) enum ParseResult<T, F> {
307301 /// end of macro invocation. Otherwise, it indicates that no rules expected the given token.
308302 /// The usize is the approximate position of the token in the input token stream.
309303 Failure(F),
310 /// Fatal error (malformed macro?). Abort compilation.
311 Error(rustc_span::Span, String),
304 /// The input could be parsed in multiple distinct ways.
305 Ambiguity,
312306 ErrorReported(ErrorGuaranteed),
313307}
314308
......@@ -429,8 +423,6 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool {
429423// Note: the vectors could be created and dropped within `parse_tt`, but to avoid excess
430424// allocations we have a single vector for each kind that is cleared and reused repeatedly.
431425pub(crate) struct TtParser {
432 macro_name: Ident,
433
434426 /// The set of current mps to be processed. This should be empty by the end of a successful
435427 /// execution of `parse_tt_inner`.
436428 cur_mps: Vec<MatcherPos>,
......@@ -448,9 +440,8 @@ pub(crate) struct TtParser {
448440}
449441
450442impl TtParser {
451 pub(super) fn new(macro_name: Ident) -> TtParser {
443 pub(super) fn new() -> TtParser {
452444 TtParser {
453 macro_name,
454445 cur_mps: vec![],
455446 next_mps: vec![],
456447 bb_mps: vec![],
......@@ -471,14 +462,14 @@ impl TtParser {
471462 /// track of through the mps generated.
472463 fn parse_tt_inner<'matcher, T: Tracker<'matcher>>(
473464 &mut self,
465 parser: &Parser<'_>,
474466 matcher: &'matcher [MatcherLoc],
475 token: &Token,
476 approx_position: u32,
477467 track: &mut T,
478468 ) -> Option<NamedParseResult<T::Failure>> {
479469 // Matcher positions that would be valid if the macro invocation was over now. Only
480470 // modified if `token == Eof`.
481 let mut eof_mps = EofMatcherPositions::None;
471 let token = &parser.token;
472 let mut eof_mps = SmallVec::<[MatcherPos; 1]>::new();
482473
483474 while let Some(mut mp) = self.cur_mps.pop() {
484475 let matcher_loc = &matcher[mp.idx];
......@@ -582,12 +573,7 @@ impl TtParser {
582573 // We are past the matcher's end, and not in a sequence. Try to end things.
583574 debug_assert_eq!(mp.idx, matcher.len() - 1);
584575 if *token == token::Eof {
585 eof_mps = match eof_mps {
586 EofMatcherPositions::None => EofMatcherPositions::One(mp),
587 EofMatcherPositions::One(_) | EofMatcherPositions::Multiple => {
588 EofMatcherPositions::Multiple
589 }
590 }
576 eof_mps.push(mp);
591577 }
592578 }
593579 }
......@@ -596,24 +582,23 @@ impl TtParser {
596582 // If we reached the end of input, check that there is EXACTLY ONE possible matcher.
597583 // Otherwise, either the parse is ambiguous (which is an error) or there is a syntax error.
598584 if *token == token::Eof {
599 Some(match eof_mps {
600 EofMatcherPositions::One(mut eof_mp) => {
585 Some(match *eof_mps {
586 [_] => {
587 let mut eof_mp = eof_mps.pop().unwrap();
601588 // Need to take ownership of the matches from within the `Rc`.
602589 Rc::make_mut(&mut eof_mp.matches);
603590 let matches = Rc::try_unwrap(eof_mp.matches).unwrap().into_iter();
604 self.nameize(matcher, matches)
591 Success(self.nameize(matcher, matches))
605592 }
606 EofMatcherPositions::Multiple => {
607 Error(token.span, "ambiguity: multiple successful parses".to_string())
608 }
609 EofMatcherPositions::None => Failure(T::build_failure(
593 [] => Failure(T::build_failure(
610594 Token::new(
611595 token::Eof,
612596 if token.span.is_dummy() { token.span } else { token.span.shrink_to_hi() },
613597 ),
614 approx_position,
598 parser.approx_token_stream_pos(),
615599 "missing tokens in macro arguments",
616600 )),
601 _ => self.ambiguity_error(parser, matcher, track),
617602 })
618603 } else {
619604 None
......@@ -641,12 +626,7 @@ impl TtParser {
641626
642627 // Process `cur_mps` until either we have finished the input or we need to get some
643628 // parsing from the black-box parser done.
644 let res = self.parse_tt_inner(
645 matcher,
646 &parser.token,
647 parser.approx_token_stream_pos(),
648 track,
649 );
629 let res = self.parse_tt_inner(parser, matcher, track);
650630
651631 if let Some(res) = res {
652632 return res;
......@@ -678,36 +658,25 @@ impl TtParser {
678658 // We need to call the black-box parser to get some nonterminal.
679659 let mut mp = self.bb_mps.pop().unwrap();
680660 let loc = &matcher[mp.idx];
681 if let &MatcherLoc::MetaVarDecl {
682 span, kind, next_metavar, seq_depth, ..
683 } = loc
684 {
685 // We use the span of the metavariable declaration to determine any
686 // edition-specific matching behavior for non-terminals.
687 let nt = match parser.to_mut().parse_nonterminal(kind) {
688 Err(err) => {
689 let guarantee = err.with_span_label(
690 span,
691 format!(
692 "while parsing argument for this `{kind}` macro fragment"
693 ),
694 )
695 .emit();
696 return ErrorReported(guarantee);
697 }
698 Ok(nt) => nt,
699 };
700 mp.push_match(next_metavar, seq_depth, MatchedSingle(nt));
701 mp.idx += 1;
702 } else {
661 let MatcherLoc::MetaVarDecl { kind, next_metavar, seq_depth, .. } = *loc else {
703662 unreachable!()
704 }
663 };
664
665 // We use the span of the metavariable declaration to determine any
666 // edition-specific matching behavior for non-terminals.
667 let nt = match parser.to_mut().parse_nonterminal(kind) {
668 Err(err) => return self.nt_parsing_error(loc, err),
669 Ok(nt) => nt,
670 };
671 mp.push_match(next_metavar, seq_depth, MatchedSingle(nt));
672
673 mp.idx += 1;
705674 self.cur_mps.push(mp);
706675 }
707676
708677 (_, _) => {
709678 // Too many possibilities!
710 return self.ambiguity_error(matcher, parser.token.span);
679 return self.ambiguity_error(parser, matcher, track);
711680 }
712681 }
713682
......@@ -715,54 +684,51 @@ impl TtParser {
715684 }
716685 }
717686
718 fn ambiguity_error<F>(
687 fn nt_parsing_error<F>(&self, loc: &MatcherLoc, err: Diag<'_>) -> NamedParseResult<F> {
688 let &MatcherLoc::MetaVarDecl { span, kind, .. } = loc else { unreachable!() };
689 let guarantee = err
690 .with_span_label(
691 span,
692 format!("while parsing argument for this `{kind}` macro fragment"),
693 )
694 .emit();
695 ErrorReported(guarantee)
696 }
697
698 fn ambiguity_error<'matcher, T: Tracker<'matcher>>(
719699 &self,
720 matcher: &[MatcherLoc],
721 token_span: rustc_span::Span,
722 ) -> NamedParseResult<F> {
723 let nts = self
724 .bb_mps
725 .iter()
726 .map(|mp| match &matcher[mp.idx] {
727 MatcherLoc::MetaVarDecl { bind, kind, .. } => {
728 format!("{kind} ('{bind}')")
729 }
730 _ => unreachable!(),
731 })
732 .collect::<Vec<String>>()
733 .join(" or ");
734
735 Error(
736 token_span,
737 format!(
738 "local ambiguity when calling macro `{}`: multiple parsing options: {}",
739 self.macro_name,
740 match self.next_mps.len() {
741 0 => format!("built-in NTs {nts}."),
742 n => format!("built-in NTs {nts} or {n} other option{s}.", s = pluralize!(n)),
743 }
744 ),
745 )
700 parser: &Parser<'_>,
701 matcher: &'matcher [MatcherLoc],
702 track: &mut T,
703 ) -> NamedParseResult<T::Failure> {
704 let bb_locs = self.bb_mps.iter().map(|mp| &matcher[mp.idx]);
705 let next_locs = self.next_mps.iter().map(|mp| &matcher[mp.idx]);
706 track.ambiguity(parser, bb_locs, next_locs);
707 Ambiguity
746708 }
747709
748 fn nameize<I: Iterator<Item = NamedMatch>, F>(
710 fn nameize<I: Iterator<Item = NamedMatch>>(
749711 &self,
750712 matcher: &[MatcherLoc],
751713 mut res: I,
752 ) -> NamedParseResult<F> {
714 ) -> NamedMatches {
753715 // Make that each metavar has _exactly one_ binding. If so, insert the binding into the
754716 // `NamedParseResult`. Otherwise, it's an error.
755717 let mut ret_val = FxHashMap::default();
756718 for loc in matcher {
757 if let &MatcherLoc::MetaVarDecl { span, bind, .. } = loc {
758 match ret_val.entry(MacroRulesNormalizedIdent::new(bind)) {
759 Vacant(spot) => spot.insert(res.next().unwrap()),
760 Occupied(..) => {
761 return Error(span, format!("duplicated bind name: {bind}"));
762 }
763 };
719 if let &MatcherLoc::MetaVarDecl { span, bind, .. } = loc
720 && ret_val
721 .insert(MacroRulesNormalizedIdent::new(bind), res.next().unwrap())
722 .is_some()
723 {
724 // Duplicate binds are checked for when the macro definition is processed,
725 // and should have prevented the definition from ever being used.
726 span_bug!(
727 span,
728 "duplicate meta-variable binding went undetected at macro definition"
729 )
764730 }
765731 }
766 Success(ret_val)
732 ret_val
767733 }
768734}
compiler/rustc_expand/src/mbe/macro_rules.rs+69-17
......@@ -40,7 +40,7 @@ use crate::base::{
4040use crate::diagnostics;
4141use crate::expand::{AstFragment, AstFragmentKind, ensure_complete_parse, parse_ast_fragment};
4242use crate::mbe::macro_check::check_meta_variables;
43use crate::mbe::macro_parser::{Error, ErrorReported, Failure, MatcherLoc, Success, TtParser};
43use crate::mbe::macro_parser::{Ambiguity, ErrorReported, Failure, MatcherLoc, Success, TtParser};
4444use crate::mbe::quoted::{RulePart, parse_one_tt};
4545use crate::mbe::transcribe::transcribe;
4646use crate::mbe::{self, KleeneOp};
......@@ -162,6 +162,32 @@ pub(crate) enum MacroRule {
162162 Derive { body: Vec<MatcherLoc>, body_span: Span, rhs: mbe::TokenTree },
163163}
164164
165/// A selection of a matcher in a [`MacroRule`].
166///
167/// [`MacroRule::Attr`] has two different matchers (args and body). This enum allows distinguishing
168/// between them, even when used for other kinds of rules.
169///
170/// This type implements [`Ord`]. The arms within a rule come in a fixed order and this type is
171/// consistent with that ordering.
172#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
173pub(crate) enum WhichMatcher {
174 /// The arguments of an attr macro ([`MacroRule::Attr::args`]).
175 Args,
176
177 /// The body of an attr macro ([`MacroRule::Attr::body`]), **or** the only arm of the rule.
178 ///
179 /// This is also used to express the only arm in a [`MacroRule::Func`] or [`MacroRule::Derive`].
180 Body,
181}
182
183impl WhichMatcher {
184 /// The [`WhichMatcher`] for [`MacroRule::Func`].
185 pub(crate) const FOR_FUNC: Self = Self::Body;
186
187 /// The [`WhichMatcher`] for [`MacroRule::Derive`].
188 pub(crate) const FOR_DERIVE: Self = Self::Body;
189}
190
165191pub struct MacroRulesMacroExpander {
166192 node_id: NodeId,
167193 name: Ident,
......@@ -342,18 +368,23 @@ pub(super) trait Tracker<'matcher> {
342368 fn build_failure(tok: Token, position: u32, msg: &'static str) -> Self::Failure;
343369
344370 /// This is called before trying to match next MatcherLoc on the current token.
345 fn before_match_loc(&mut self, _parser: &TtParser, _matcher: &'matcher MatcherLoc) {}
371 fn before_match_loc(&mut self, parser: &TtParser, matcher: &'matcher MatcherLoc);
346372
347373 /// This is called after an arm has been parsed, either successfully or unsuccessfully. When
348374 /// this is called, `before_match_loc` was called at least once (with a `MatcherLoc::Eof`).
349 fn after_arm(&mut self, _in_body: bool, _result: &NamedParseResult<Self::Failure>) {}
375 fn after_arm(&mut self, which_matcher: WhichMatcher, result: &NamedParseResult<Self::Failure>);
376
377 fn ambiguity(
378 &mut self,
379 parser: &Parser<'_>,
380 bb_locs: impl IntoIterator<Item = &'matcher MatcherLoc>,
381 next_locs: impl IntoIterator<Item = &'matcher MatcherLoc>,
382 );
350383
351384 /// For tracing.
352385 fn description() -> &'static str;
353386
354 fn recovery() -> Recovery {
355 Recovery::Forbidden
356 }
387 fn recovery() -> Recovery;
357388}
358389
359390/// A noop tracker that is used in the hot path of the expansion, has zero overhead thanks to
......@@ -365,9 +396,30 @@ impl<'matcher> Tracker<'matcher> for NoopTracker {
365396
366397 fn build_failure(_tok: Token, _position: u32, _msg: &'static str) -> Self::Failure {}
367398
399 fn before_match_loc(&mut self, _parser: &TtParser, _matcher: &'matcher MatcherLoc) {}
400
401 fn ambiguity(
402 &mut self,
403 _parser: &Parser<'_>,
404 _bb_locs: impl IntoIterator<Item = &'matcher MatcherLoc>,
405 _next_locs: impl IntoIterator<Item = &'matcher MatcherLoc>,
406 ) {
407 }
408
409 fn after_arm(
410 &mut self,
411 _which_matcher: WhichMatcher,
412 _result: &NamedParseResult<Self::Failure>,
413 ) {
414 }
415
368416 fn description() -> &'static str {
369417 "none"
370418 }
419
420 fn recovery() -> Recovery {
421 Recovery::Forbidden
422 }
371423}
372424
373425/// Expands the rules based macro defined by `rules` for a given input `arg`.
......@@ -572,7 +624,7 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
572624 // this situation.)
573625 let parser = parser_from_cx(psess, arg.clone(), T::recovery());
574626 // Try each arm's matchers.
575 let mut tt_parser = TtParser::new(name);
627 let mut tt_parser = TtParser::new();
576628 for (i, rule) in rules.iter().enumerate() {
577629 let MacroRule::Func { lhs, .. } = rule else { continue };
578630 let _tracing_span = trace_span!("Matching arm", %i);
......@@ -585,7 +637,7 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
585637
586638 let result = tt_parser.parse_tt(&mut Cow::Borrowed(&parser), lhs, track);
587639
588 track.after_arm(true, &result);
640 track.after_arm(WhichMatcher::FOR_FUNC, &result);
589641
590642 match result {
591643 Success(named_matches) => {
......@@ -600,7 +652,7 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
600652 trace!("Failed to match arm, trying the next one");
601653 // Try the next arm.
602654 }
603 Error(_, _) => {
655 Ambiguity => {
604656 debug!("Fatal error occurred during matching");
605657 // We haven't emitted an error yet, so we can retry.
606658 return Err(CanRetry::Yes);
......@@ -635,14 +687,14 @@ pub(super) fn try_match_macro_attr<'matcher, T: Tracker<'matcher>>(
635687 // This uses the same strategy as `try_match_macro`
636688 let args_parser = parser_from_cx(psess, attr_args.clone(), T::recovery());
637689 let body_parser = parser_from_cx(psess, attr_body.clone(), T::recovery());
638 let mut tt_parser = TtParser::new(name);
690 let mut tt_parser = TtParser::new();
639691 for (i, rule) in rules.iter().enumerate() {
640692 let MacroRule::Attr { args, body, .. } = rule else { continue };
641693
642694 let mut gated_spans_snapshot = mem::take(&mut *psess.gated_spans.spans.borrow_mut());
643695
644696 let result = tt_parser.parse_tt(&mut Cow::Borrowed(&args_parser), args, track);
645 track.after_arm(false, &result);
697 track.after_arm(WhichMatcher::Args, &result);
646698
647699 let mut named_matches = match result {
648700 Success(named_matches) => named_matches,
......@@ -650,12 +702,12 @@ pub(super) fn try_match_macro_attr<'matcher, T: Tracker<'matcher>>(
650702 mem::swap(&mut gated_spans_snapshot, &mut psess.gated_spans.spans.borrow_mut());
651703 continue;
652704 }
653 Error(_, _) => return Err(CanRetry::Yes),
705 Ambiguity => return Err(CanRetry::Yes),
654706 ErrorReported(guar) => return Err(CanRetry::No(guar)),
655707 };
656708
657709 let result = tt_parser.parse_tt(&mut Cow::Borrowed(&body_parser), body, track);
658 track.after_arm(true, &result);
710 track.after_arm(WhichMatcher::Body, &result);
659711
660712 match result {
661713 Success(body_named_matches) => {
......@@ -667,7 +719,7 @@ pub(super) fn try_match_macro_attr<'matcher, T: Tracker<'matcher>>(
667719 Failure(_) => {
668720 mem::swap(&mut gated_spans_snapshot, &mut psess.gated_spans.spans.borrow_mut())
669721 }
670 Error(_, _) => return Err(CanRetry::Yes),
722 Ambiguity => return Err(CanRetry::Yes),
671723 ErrorReported(guar) => return Err(CanRetry::No(guar)),
672724 }
673725 }
......@@ -688,14 +740,14 @@ pub(super) fn try_match_macro_derive<'matcher, T: Tracker<'matcher>>(
688740) -> Result<(usize, &'matcher MacroRule, NamedMatches), CanRetry> {
689741 // This uses the same strategy as `try_match_macro`
690742 let body_parser = parser_from_cx(psess, body.clone(), T::recovery());
691 let mut tt_parser = TtParser::new(name);
743 let mut tt_parser = TtParser::new();
692744 for (i, rule) in rules.iter().enumerate() {
693745 let MacroRule::Derive { body, .. } = rule else { continue };
694746
695747 let mut gated_spans_snapshot = mem::take(&mut *psess.gated_spans.spans.borrow_mut());
696748
697749 let result = tt_parser.parse_tt(&mut Cow::Borrowed(&body_parser), body, track);
698 track.after_arm(true, &result);
750 track.after_arm(WhichMatcher::FOR_DERIVE, &result);
699751
700752 match result {
701753 Success(named_matches) => {
......@@ -705,7 +757,7 @@ pub(super) fn try_match_macro_derive<'matcher, T: Tracker<'matcher>>(
705757 Failure(_) => {
706758 mem::swap(&mut gated_spans_snapshot, &mut psess.gated_spans.spans.borrow_mut())
707759 }
708 Error(_, _) => return Err(CanRetry::Yes),
760 Ambiguity => return Err(CanRetry::Yes),
709761 ErrorReported(guar) => return Err(CanRetry::No(guar)),
710762 }
711763 }