Skip to content

Commit

Permalink
Improve handling of spans around macro result parse errors
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Aaron1011 committed Jan 31, 2021
1 parent 04caa63 commit 6c14aad
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 4 deletions.
4 changes: 3 additions & 1 deletion compiler/rustc_expand/src/expand.rs
Expand Up @@ -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();
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Expand Up @@ -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.
Expand Down Expand Up @@ -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))
}
_ => (
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_span/src/source_map.rs
Expand Up @@ -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);
Expand Down
14 changes: 14 additions & 0 deletions 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() {}
8 changes: 8 additions & 0 deletions 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

7 changes: 6 additions & 1 deletion src/test/ui/proc-macro/lifetimes.stderr
Expand Up @@ -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

0 comments on commit 6c14aad

Please sign in to comment.