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.
This commit is contained in:
Aaron Hill 2021-06-07 20:17:48 -05:00
parent e4a6032706
commit 822f800ad7
No known key found for this signature in database
GPG Key ID: B4087E510E98B164
4 changed files with 13 additions and 7 deletions

View File

@ -1,6 +1,7 @@
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![feature(decl_macro)] #![feature(decl_macro)]
#![feature(destructuring_assignment)] #![feature(destructuring_assignment)]
#![feature(format_args_capture)]
#![feature(iter_zip)] #![feature(iter_zip)]
#![feature(proc_macro_diagnostic)] #![feature(proc_macro_diagnostic)]
#![feature(proc_macro_internals)] #![feature(proc_macro_internals)]

View File

@ -85,6 +85,7 @@
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_span::symbol::Ident;
use std::borrow::Cow; use std::borrow::Cow;
use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::mem; 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 /// 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. /// 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 // 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 // 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 // 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( return Error(
parser.token.span, parser.token.span,
format!( format!(
"local ambiguity: multiple parsing options: {}", "local ambiguity when calling macro `{macro_name}`: multiple parsing options: {}",
match next_items.len() { match next_items.len() {
0 => format!("built-in NTs {}.", nts), 0 => format!("built-in NTs {}.", nts),
1 => format!("built-in NTs {} or 1 other option.", nts), 1 => format!("built-in NTs {} or 1 other option.", nts),

View File

@ -245,7 +245,7 @@ fn generic_extension<'cx>(
// are not recorded. On the first `Success(..)`ful matcher, the spans are merged. // 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()); 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) => { Success(named_matches) => {
// The matcher was `Success(..)`ful. // The matcher was `Success(..)`ful.
// Merge the gated spans from parsing the matcher with the pre-existing ones. // Merge the gated spans from parsing the matcher with the pre-existing ones.
@ -338,7 +338,7 @@ fn generic_extension<'cx>(
_ => continue, _ => continue,
}; };
if let Success(_) = 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() { if comma_span.is_dummy() {
err.note("you might be missing a comma"); 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 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, Success(m) => m,
Failure(token, msg) => { Failure(token, msg) => {
let s = parse_failure_msg(&token); let s = parse_failure_msg(&token);

View File

@ -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 --> $DIR/local-ambiguity-multiple-parsing-options.rs:7:12
| |
LL | ambiguity!(error); 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 --> $DIR/local-ambiguity-multiple-parsing-options.rs:8:12
| |
LL | ambiguity!(error); LL | ambiguity!(error);