}
pub(super) trait Tracker<'matcher> {
- /// This is called before trying to match next MatcherLoc on the current token
+ /// This is called before trying to match next MatcherLoc on the current token.
fn before_match_loc(&mut self, parser: &TtParser, matcher: &'matcher MatcherLoc);
/// This is called after an arm has been parsed, either successfully or unsuccessfully. When this is called,
- /// `before_match_loc` was called at least once (with a `MatcherLoc::Eof`)
+ /// `before_match_loc` was called at least once (with a `MatcherLoc::Eof`).
fn after_arm(&mut self, result: &NamedParseResult);
- /// For tracing
+ /// For tracing.
fn description() -> &'static str;
}
-/// A noop tracker that is used in the hot path of the expansion, has zero overhead thanks to monomorphization
+/// A noop tracker that is used in the hot path of the expansion, has zero overhead thanks to monomorphization.
struct NoopTracker;
impl<'matcher> Tracker<'matcher> for NoopTracker {
/// Expands the rules based macro defined by `lhses` and `rhses` for a given
/// input `arg`.
+#[instrument(skip(cx, transparency, arg, lhses, rhses))]
fn expand_macro<'cx>(
cx: &'cx mut ExtCtxt<'_>,
sp: Span,
trace_macros_note(&mut cx.expansions, sp, msg);
}
- // Track nothing for the best performance
+ // Track nothing for the best performance.
let try_success_result = try_match_macro(sess, name, &arg, lhses, &mut NoopTracker);
match try_success_result {
}
}
- // An error occured, try the expansion again, tracking the expansion closely for better diagnostics
+ // An error occurred, try the expansion again, tracking the expansion closely for better diagnostics.
let mut tracker = CollectTrackerAndEmitter::new(cx, sp);
let try_success_result = try_match_macro(sess, name, &arg, lhses, &mut tracker);
DummyResult::any(sp)
}
-/// The tracker used for the slow error path that collects useful info for diagnostics
+/// The tracker used for the slow error path that collects useful info for diagnostics.
struct CollectTrackerAndEmitter<'a, 'cx> {
cx: &'a mut ExtCtxt<'cx>,
/// Which arm's failure should we report? (the one furthest along)
No(ErrorGuaranteed),
}
-/// Try expanding the macro. Returns the index of the sucessful arm and its named_matches if it was successful,
+/// Try expanding the macro. Returns the index of the successful arm and its named_matches if it was successful,
/// and nothing if it failed. On failure, it's the callers job to use `track` accordingly to record all errors
/// correctly.
+#[instrument(level = "debug", skip(sess, arg, lhses, track), fields(tracking = %T::description()))]
fn try_match_macro<'matcher, T: Tracker<'matcher>>(
sess: &ParseSess,
name: Ident,
// Try each arm's matchers.
let mut tt_parser = TtParser::new(name);
for (i, lhs) in lhses.iter().enumerate() {
+ let _tracing_span = trace_span!("Matching arm", %i);
+
// Take a snapshot of the state of pre-expansion gating at this point.
// This is used so that if a matcher is not `Success(..)`ful,
// then the spans which became gated when parsing the unsuccessful matcher
match result {
Success(named_matches) => {
+ debug!("Parsed arm successfully");
// The matcher was `Success(..)`ful.
// Merge the gated spans from parsing the matcher with the pre-existing ones.
sess.gated_spans.merge(gated_spans_snapshot);
return Ok((i, named_matches));
}
Failure(_, _) => {
- // Try the next arm
+ trace!("Failed to match arm, trying the next one");
+ // Try the next arm.
}
Error(_, _) => {
- // We haven't emitted an error yet
+ debug!("Fatal error occurred during matching");
+ // We haven't emitted an error yet, so we can retry.
return Err(CanRetry::Yes);
}
ErrorReported(guarantee) => {
+ debug!("Fatal error occurred and was reported during matching");
+ // An error has been reported already, we cannot retry as that would cause duplicate errors.
return Err(CanRetry::No(guarantee));
}
}