about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-04-25 18:30:22 +0200
committerGitHub <noreply@github.com>2020-04-25 18:30:22 +0200
commit7b7c63cb7732e5ad5eace294b1c7c2f92beef4a2 (patch)
tree07ab72a6d8d0adf30ca2fd8dad25739b63a524cc
parentb613c989594f1cbf0d4af1a7a153786cca7792c8 (diff)
parent966a295e8cc210d7b50185d16cb46a7ae1874531 (diff)
downloadrust-7b7c63cb7732e5ad5eace294b1c7c2f92beef4a2.tar.gz
rust-7b7c63cb7732e5ad5eace294b1c7c2f92beef4a2.zip
Rollup merge of #69041 - petrochenkov:stabmodispan, r=Amanieu
proc_macro: Stabilize `Span::resolved_at` and `Span::located_at`

Introduced in https://github.com/rust-lang/rust/pull/47149.
Part of https://github.com/rust-lang/rust/issues/54725.

Motivation: https://github.com/rust-lang/rust/pull/68716#issuecomment-583918919.
Identifiers in proc macros may want to inherit span locations for diagnostics from one tokens (e.g. some tokens from the macro input), but resolve those identifiers from some different location (e.g. from the macro's definition site).
This becomes especially important when multiple resolution locations become available with stabilization of [`Span::mixed_site`](https://github.com/rust-lang/rust/pull/68716).

Why I think this is the right API for setting span's location and hygiene - https://github.com/rust-lang/rust/pull/69041#issuecomment-586644778.

r? @dtolnay
-rw-r--r--src/libproc_macro/lib.rs4
-rw-r--r--src/test/ui/proc-macro/auxiliary/resolved-located-at.rs32
-rw-r--r--src/test/ui/proc-macro/resolved-located-at.rs12
-rw-r--r--src/test/ui/proc-macro/resolved-located-at.stderr21
4 files changed, 67 insertions, 2 deletions
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index 3cbe852de7b..6e49d9829a2 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -352,14 +352,14 @@ impl Span {
 
     /// Creates a new span with the same line/column information as `self` but
     /// that resolves symbols as though it were at `other`.
-    #[unstable(feature = "proc_macro_span", issue = "54725")]
+    #[stable(feature = "proc_macro_span_resolved_at", since = "1.43.0")]
     pub fn resolved_at(&self, other: Span) -> Span {
         Span(self.0.resolved_at(other.0))
     }
 
     /// Creates a new span with the same name resolution behavior as `self` but
     /// with the line/column information of `other`.
-    #[unstable(feature = "proc_macro_span", issue = "54725")]
+    #[stable(feature = "proc_macro_span_located_at", since = "1.43.0")]
     pub fn located_at(&self, other: Span) -> Span {
         other.resolved_at(*self)
     }
diff --git a/src/test/ui/proc-macro/auxiliary/resolved-located-at.rs b/src/test/ui/proc-macro/auxiliary/resolved-located-at.rs
new file mode 100644
index 00000000000..9416c133e56
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/resolved-located-at.rs
@@ -0,0 +1,32 @@
+// force-host
+// no-prefer-dynamic
+
+#![feature(proc_macro_def_site)]
+#![feature(proc_macro_diagnostic)]
+#![feature(proc_macro_hygiene)]
+#![feature(proc_macro_quote)]
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn resolve_located_at(input: TokenStream) -> TokenStream {
+    match &*input.into_iter().collect::<Vec<_>>() {
+        [a, b, ..] => {
+            // The error is reported at input `a`.
+            let mut diag = Diagnostic::new(Level::Error, "expected error");
+            diag.set_spans(Span::def_site().located_at(a.span()));
+            diag.emit();
+
+            // Resolves to `struct S;` at def site, but the error is reported at input `b`.
+            let s = TokenTree::Ident(Ident::new("S", b.span().resolved_at(Span::def_site())));
+            quote!({
+                struct S;
+
+                $s
+            })
+        }
+        _ => panic!("unexpected input"),
+    }
+}
diff --git a/src/test/ui/proc-macro/resolved-located-at.rs b/src/test/ui/proc-macro/resolved-located-at.rs
new file mode 100644
index 00000000000..9976284e222
--- /dev/null
+++ b/src/test/ui/proc-macro/resolved-located-at.rs
@@ -0,0 +1,12 @@
+// aux-build:resolved-located-at.rs
+
+#![feature(proc_macro_hygiene)]
+
+#[macro_use]
+extern crate resolved_located_at;
+
+fn main() {
+    resolve_located_at!(a b)
+    //~^ ERROR expected error
+    //~| ERROR mismatched types
+}
diff --git a/src/test/ui/proc-macro/resolved-located-at.stderr b/src/test/ui/proc-macro/resolved-located-at.stderr
new file mode 100644
index 00000000000..0df7ced27a7
--- /dev/null
+++ b/src/test/ui/proc-macro/resolved-located-at.stderr
@@ -0,0 +1,21 @@
+error: expected error
+  --> $DIR/resolved-located-at.rs:9:25
+   |
+LL |     resolve_located_at!(a b)
+   |                         ^
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/resolved-located-at.rs:9:27
+   |
+LL | fn main() {
+   |           - expected `()` because of default return type
+LL |     resolve_located_at!(a b)
+   |                           ^ expected `()`, found struct `main::S`
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.