about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJonas Schievink <jonasschievink@gmail.com>2021-02-02 12:15:02 +0100
committerGitHub <noreply@github.com>2021-02-02 12:15:02 +0100
commit255e0764c071d73a43a0c88181cb4cf667a74bff (patch)
treec57981a97579414d5675173adc20c6fd8c5e6866
parent86d0e6d257d8546b07417b863ef2f5d62bf7ce19 (diff)
parent6c14aad58e65c9c50faa45ed88369c5c72d6d0d7 (diff)
downloadrust-255e0764c071d73a43a0c88181cb4cf667a74bff.tar.gz
rust-255e0764c071d73a43a0c88181cb4cf667a74bff.zip
Rollup merge of #81608 - Aaron1011:macro-res-parse-err, r=davidtwco
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
-rw-r--r--compiler/rustc_expand/src/expand.rs4
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs4
-rw-r--r--compiler/rustc_span/src/source_map.rs3
-rw-r--r--src/test/ui/proc-macro/issue-81543-item-parse-err.rs14
-rw-r--r--src/test/ui/proc-macro/issue-81543-item-parse-err.stderr8
-rw-r--r--src/test/ui/proc-macro/lifetimes.stderr7
6 files changed, 36 insertions, 4 deletions
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 50832d5edbf..5fdb7fc5915 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 f2fcce5c226..5512e849c45 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 4e0ce0d344d..2b429372dcf 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 00000000000..027389556fe
--- /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 00000000000..ca524176035
--- /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 10acd4304aa..58f6165388c 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