From 822f800ad74c7d43fc8b9170558e144726c3f777 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 7 Jun 2021 20:17:48 -0500 Subject: [PATCH] Include macro name in 'local ambiguity' error Currently, we only point at the span of the macro argument. When the macro call is itself generated by another macro, this can make it difficult or impossible to determine which macro is responsible for producing the error. --- compiler/rustc_expand/src/lib.rs | 1 + compiler/rustc_expand/src/mbe/macro_parser.rs | 9 +++++++-- compiler/rustc_expand/src/mbe/macro_rules.rs | 6 +++--- .../local-ambiguity-multiple-parsing-options.stderr | 4 ++-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index f77eac2b068..efed41de23a 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -1,6 +1,7 @@ #![feature(crate_visibility_modifier)] #![feature(decl_macro)] #![feature(destructuring_assignment)] +#![feature(format_args_capture)] #![feature(iter_zip)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 1aed42a24e2..a7434d73abe 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -85,6 +85,7 @@ use smallvec::{smallvec, SmallVec}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; +use rustc_span::symbol::Ident; use std::borrow::Cow; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::mem; @@ -615,7 +616,11 @@ fn inner_parse_loop<'root, 'tt>( /// Use the given sequence of token trees (`ms`) as a matcher. Match the token /// stream from the given `parser` against it and return the match. -pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> NamedParseResult { +pub(super) fn parse_tt( + parser: &mut Cow<'_, Parser<'_>>, + ms: &[TokenTree], + macro_name: Ident, +) -> NamedParseResult { // A queue of possible matcher positions. We initialize it with the matcher position in which // the "dot" is before the first token of the first token tree in `ms`. `inner_parse_loop` then // processes all of these possible matcher positions and produces possible next positions into @@ -711,7 +716,7 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na return Error( parser.token.span, format!( - "local ambiguity: multiple parsing options: {}", + "local ambiguity when calling macro `{macro_name}`: multiple parsing options: {}", match next_items.len() { 0 => format!("built-in NTs {}.", nts), 1 => format!("built-in NTs {} or 1 other option.", nts), diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 6608573d720..abad190b072 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -245,7 +245,7 @@ fn generic_extension<'cx>( // are not recorded. On the first `Success(..)`ful matcher, the spans are merged. let mut gated_spans_snapshot = mem::take(&mut *sess.gated_spans.spans.borrow_mut()); - match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) { + match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt, name) { Success(named_matches) => { // The matcher was `Success(..)`ful. // Merge the gated spans from parsing the matcher with the pre-existing ones. @@ -338,7 +338,7 @@ fn generic_extension<'cx>( _ => continue, }; if let Success(_) = - parse_tt(&mut Cow::Borrowed(&parser_from_cx(sess, arg.clone())), lhs_tt) + parse_tt(&mut Cow::Borrowed(&parser_from_cx(sess, arg.clone())), lhs_tt, name) { if comma_span.is_dummy() { err.note("you might be missing a comma"); @@ -432,7 +432,7 @@ pub fn compile_declarative_macro( ]; let parser = Parser::new(&sess.parse_sess, body, true, rustc_parse::MACRO_ARGUMENTS); - let argument_map = match parse_tt(&mut Cow::Borrowed(&parser), &argument_gram) { + let argument_map = match parse_tt(&mut Cow::Borrowed(&parser), &argument_gram, def.ident) { Success(m) => m, Failure(token, msg) => { let s = parse_failure_msg(&token); diff --git a/src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr b/src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr index 0ae56c42221..68b278fd3c8 100644 --- a/src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr +++ b/src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr @@ -1,10 +1,10 @@ -error: local ambiguity: multiple parsing options: built-in NTs ident ('i') or ident ('j'). +error: local ambiguity when calling macro `ambiguity`: multiple parsing options: built-in NTs ident ('i') or ident ('j'). --> $DIR/local-ambiguity-multiple-parsing-options.rs:7:12 | LL | ambiguity!(error); | ^^^^^ -error: local ambiguity: multiple parsing options: built-in NTs ident ('i') or ident ('j'). +error: local ambiguity when calling macro `ambiguity`: multiple parsing options: built-in NTs ident ('i') or ident ('j'). --> $DIR/local-ambiguity-multiple-parsing-options.rs:8:12 | LL | ambiguity!(error);