Change:
one of the desired output should be much help, rather than: No response No response <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim

Discussion:
let span = token.span.substitute_dummy(sp); <del> let mut err = cx.dcx().struct_span_err(span, parse_failure_msg(&token)); </del> <ins> let mut err = cx.dcx().struct_span_err(span, parse_failure_msg(&token, None)); </ins> err.span_label(span, label); if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) { err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro");

} /// Currently used by macro_rules! compilation to extract a little information from the `Failure` case. <del> pub struct FailureForwarder; </del> <ins> pub struct FailureForwarder<'matcher> { expected_token: Option<&'matcher Token>, } impl<'matcher> FailureForwarder<'matcher> { pub fn new() -> Self { Self { expected_token: None } } } </ins> <del> impl<'matcher> Tracker<'matcher> for FailureForwarder { </del> <ins> impl<'matcher> Tracker<'matcher> for FailureForwarder<'matcher> { </ins> type Failure = (Token, usize, &'static str); fn build_failure(tok: Token, position: usize, msg: &'static str) -> Self::Failure {

fn description() -> &'static str { "failure-forwarder" } <ins> fn set_expected_token(&mut self, tok: &'matcher Token) { self.expected_token = Some(tok); } fn get_expected_token(&self) -> Option<&'matcher Token> { self.expected_token } </ins> } pub(super) fn emit_frag_parse_err(

/// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For /// other tokens, this is "unexpected token...". <del> pub(super) fn parse_failure_msg(tok: &Token) -> Cow<'static, str> { match tok.kind { token::Eof => Cow::from("unexpected end of macro invocation"), _ => Cow::from(format!("no rules expected the token `{}`", pprust::token_to_string(tok))), </del> <ins> pub(super) fn parse_failure_msg(tok: &Token, expected_token: Option<&Token>) -> Cow<'static, str> { if let Some(expected_token) = expected_token { Cow::from(format!( "expected `{}`, found `{}`", pprust::token_to_string(expected_token), pprust::token_to_string(tok), )) } else { match tok.kind { token::Eof => Cow::from("unexpected end of macro invocation"), _ => { Cow::from(format!("no rules expected the token `{}`", pprust::token_to_string(tok))) } } </ins> } }

// The separator matches the current token. Advance past it. mp.idx += 1; self.next_mps.push(mp); <ins> } else { track.set_expected_token(separator); </ins> } } &MatcherLoc::SequenceKleeneOpAfterSep { idx_first } => {

parser.approx_token_stream_pos(), track, ); if let Some(res) = res { return res; }

fn recovery() -> Recovery { Recovery::Forbidden } <ins> fn set_expected_token(&mut self, _tok: &'matcher Token) {} fn get_expected_token(&self) -> Option<&'matcher Token> { None } </ins> } /// A noop tracker that is used in the hot path of the expansion, has zero overhead thanks to

// For this we need to reclone the macro body as the previous parser consumed it. let retry_parser = create_parser(); <del> let parse_result = tt_parser.parse_tt( &mut Cow::Owned(retry_parser), &argument_gram, &mut diagnostics::FailureForwarder, ); </del> <ins> let mut track = diagnostics::FailureForwarder::new(); let parse_result = tt_parser.parse_tt(&mut Cow::Owned(retry_parser), &argument_gram, &mut track); </ins> let Failure((token, _, msg)) = parse_result else { unreachable!("matcher returned something other than Failure after retry"); }; <del> let s = parse_failure_msg(&token); </del> <ins> let s = parse_failure_msg(&token, track.get_expected_token()); </ins> let sp = token.span.substitute_dummy(def.span); let mut err = sess.dcx().struct_span_err(sp, s); err.span_label(sp, msg);

<ins> #[allow(unused_macros)] macro_rules! foo { () => { } () => { //~^ ERROR expected `;`, found `(` } } fn main() {} </ins>

<ins> error: expected `;`, found `(` --> $DIR/missing-semi.rs:6:5 | LL |     () => { |     ^ no rules expected this token in macro call error: aborting due to 1 previous error </ins>