From 6c14aad58e65c9c50faa45ed88369c5c72d6d0d7 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sun, 31 Jan 2021 15:21:28 -0500 Subject: [PATCH] Improve handling of spans around macro result parse errors Fixes #81543 After we expand a macro, we try to parse the resulting tokens as a AST node. This commit makes several improvements to how we handle spans when an error occurs: * Only ovewrite the original `Span` if it's a dummy span. This preserves a more-specific span if one is available. * Use `self.prev_token` instead of `self.token` when emitting an error message after encountering EOF, since an EOF token always has a dummy span * Make `SourceMap::next_point` leave dummy spans unused. A dummy span does not have a logical 'next point', since it's a zero-length span. Re-using the span span preserves its 'dummy-ness' for other checks --- compiler/rustc_expand/src/expand.rs | 4 +++- compiler/rustc_parse/src/parser/diagnostics.rs | 4 ++-- compiler/rustc_span/src/source_map.rs | 3 +++ .../ui/proc-macro/issue-81543-item-parse-err.rs | 14 ++++++++++++++ .../proc-macro/issue-81543-item-parse-err.stderr | 8 ++++++++ src/test/ui/proc-macro/lifetimes.stderr | 7 ++++++- 6 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/proc-macro/issue-81543-item-parse-err.rs create mode 100644 src/test/ui/proc-macro/issue-81543-item-parse-err.stderr diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 50832d5edbfc5..5fdb7fc591594 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -896,7 +896,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { fragment } Err(mut err) => { - err.set_span(span); + if err.span.is_dummy() { + err.set_span(span); + } annotate_err_with_kind(&mut err, kind, span); err.emit(); self.cx.trace_macros_diag(); diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index f2fcce5c22662..5512e849c451d 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1104,7 +1104,7 @@ impl<'a> Parser<'a> { let (prev_sp, sp) = match (&self.token.kind, self.subparser_name) { // Point at the end of the macro call when reaching end of macro arguments. (token::Eof, Some(_)) => { - let sp = self.sess.source_map().next_point(self.token.span); + let sp = self.sess.source_map().next_point(self.prev_token.span); (sp, sp) } // We don't want to point at the following span after DUMMY_SP. @@ -1721,7 +1721,7 @@ impl<'a> Parser<'a> { pub(super) fn expected_expression_found(&self) -> DiagnosticBuilder<'a> { let (span, msg) = match (&self.token.kind, self.subparser_name) { (&token::Eof, Some(origin)) => { - let sp = self.sess.source_map().next_point(self.token.span); + let sp = self.sess.source_map().next_point(self.prev_token.span); (sp, format!("expected expression, found end of {}", origin)) } _ => ( diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 4e0ce0d344de4..2b429372dcffb 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -799,6 +799,9 @@ impl SourceMap { /// Returns a new span representing the next character after the end-point of this span. pub fn next_point(&self, sp: Span) -> Span { + if sp.is_dummy() { + return sp; + } let start_of_next_point = sp.hi().0; let width = self.find_width_of_character_at_span(sp.shrink_to_hi(), true); diff --git a/src/test/ui/proc-macro/issue-81543-item-parse-err.rs b/src/test/ui/proc-macro/issue-81543-item-parse-err.rs new file mode 100644 index 0000000000000..027389556fe24 --- /dev/null +++ b/src/test/ui/proc-macro/issue-81543-item-parse-err.rs @@ -0,0 +1,14 @@ +// aux-build:test-macros.rs + +// Regression test for issue #81543 +// Tests that we emit a properly spanned error +// when the output of a proc-macro cannot be parsed +// as the expected AST node kind + +extern crate test_macros; + +test_macros::identity! { + fn 32() {} //~ ERROR expected identifier +} + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-81543-item-parse-err.stderr b/src/test/ui/proc-macro/issue-81543-item-parse-err.stderr new file mode 100644 index 0000000000000..ca524176035b8 --- /dev/null +++ b/src/test/ui/proc-macro/issue-81543-item-parse-err.stderr @@ -0,0 +1,8 @@ +error: expected identifier, found `32` + --> $DIR/issue-81543-item-parse-err.rs:11:8 + | +LL | fn 32() {} + | ^^ expected identifier + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/lifetimes.stderr b/src/test/ui/proc-macro/lifetimes.stderr index 10acd4304aa23..58f6165388ca1 100644 --- a/src/test/ui/proc-macro/lifetimes.stderr +++ b/src/test/ui/proc-macro/lifetimes.stderr @@ -2,7 +2,12 @@ error: expected type, found `'` --> $DIR/lifetimes.rs:7:10 | LL | type A = single_quote_alone!(); - | ^^^^^^^^^^^^^^^^^^^^^ this macro call doesn't expand to a type + | ^^^^^^^^^^^^^^^^^^^^^ + | | + | expected type + | this macro call doesn't expand to a type + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error