about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2022-08-09 17:34:55 +0530
committerGitHub <noreply@github.com>2022-08-09 17:34:55 +0530
commitfac84e8bb65349e3b26cb5c4e7acf7694b8e6659 (patch)
treed6a0fadda3123fb980d5bb4fb9599650cd0f03ed
parentd910e5376b69d232071b8eeed4d65e703e13a82b (diff)
parent15b1daaca3fd4020d7a93cff14507b9104ec6d02 (diff)
downloadrust-fac84e8bb65349e3b26cb5c4e7acf7694b8e6659.tar.gz
rust-fac84e8bb65349e3b26cb5c4e7acf7694b8e6659.zip
Rollup merge of #100228 - luqmana:suggestion-ice, r=estebank
Don't ICE while suggesting updating item path.

When an item isn't found, we may suggest an appropriate import to `use`. Along with that, we also suggest updating the path to work with the `use`. Unfortunately, if the code in question originates from a macro, the span used to indicate which part of the path needs updating may not be suitable and cause an ICE (*). Since, such code is not adjustable directly by the user without modifying the macro, just skip the suggestion in such cases.

(*) The ICE happens because the emitter want to indicate to the user what code to delete by referencing a certain span. But in this case, said span has `lo == hi == 0` which means it thinks it's a dummy span. Adding a space before the proc macro attribute is enough to stop it from ICE'ing but even then the suggestion doesn't really make any sense:
```
help: if you import `DataStore`, refer to it directly
  |
1 -  #[dbstruct::dbstruct]
1 +  #[dbstruct::dbstruct]
```

Since suggestions are best-effort, I just gated this one on `can_be_used_for_suggestions` which catches cases like this.

Fixes #100199
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs15
-rw-r--r--src/test/ui/macros/auxiliary/issue-100199.rs18
-rw-r--r--src/test/ui/macros/issue-100199.rs16
-rw-r--r--src/test/ui/macros/issue-100199.stderr15
4 files changed, 58 insertions, 6 deletions
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 8839fb1a151..325b0458638 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -2544,12 +2544,15 @@ fn show_candidates(
                 Applicability::MaybeIncorrect,
             );
             if let [first, .., last] = &path[..] {
-                err.span_suggestion_verbose(
-                    first.ident.span.until(last.ident.span),
-                    &format!("if you import `{}`, refer to it directly", last.ident),
-                    "",
-                    Applicability::Unspecified,
-                );
+                let sp = first.ident.span.until(last.ident.span);
+                if sp.can_be_used_for_suggestions() {
+                    err.span_suggestion_verbose(
+                        sp,
+                        &format!("if you import `{}`, refer to it directly", last.ident),
+                        "",
+                        Applicability::Unspecified,
+                    );
+                }
             }
         } else {
             msg.push(':');
diff --git a/src/test/ui/macros/auxiliary/issue-100199.rs b/src/test/ui/macros/auxiliary/issue-100199.rs
new file mode 100644
index 00000000000..9e190b542db
--- /dev/null
+++ b/src/test/ui/macros/auxiliary/issue-100199.rs
@@ -0,0 +1,18 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro_quote)]
+
+extern crate proc_macro;
+
+use proc_macro::{quote, Ident, Span, TokenStream, TokenTree};
+
+#[proc_macro_attribute]
+pub fn struct_with_bound(_: TokenStream, _: TokenStream) -> TokenStream {
+    let crate_ident = TokenTree::Ident(Ident::new("crate", Span::call_site()));
+    let trait_ident = TokenTree::Ident(Ident::new("MyTrait", Span::call_site()));
+    quote!(
+        struct Foo<T: $crate_ident::$trait_ident> {}
+    )
+}
diff --git a/src/test/ui/macros/issue-100199.rs b/src/test/ui/macros/issue-100199.rs
new file mode 100644
index 00000000000..6e50afa0759
--- /dev/null
+++ b/src/test/ui/macros/issue-100199.rs
@@ -0,0 +1,16 @@
+#[issue_100199::struct_with_bound] //~ ERROR cannot find trait `MyTrait` in the crate root
+struct Foo {}
+// The above must be on the first line so that it's span points to pos 0.
+// This used to trigger an ICE because the diagnostic emitter would get
+// an unexpected dummy span (lo == 0 == hi) while attempting to print a
+// suggestion.
+
+// aux-build: issue-100199.rs
+
+extern crate issue_100199;
+
+mod traits {
+    pub trait MyTrait {}
+}
+
+fn main() {}
diff --git a/src/test/ui/macros/issue-100199.stderr b/src/test/ui/macros/issue-100199.stderr
new file mode 100644
index 00000000000..2cb45dc1247
--- /dev/null
+++ b/src/test/ui/macros/issue-100199.stderr
@@ -0,0 +1,15 @@
+error[E0405]: cannot find trait `MyTrait` in the crate root
+  --> $DIR/issue-100199.rs:1:1
+   |
+LL | #[issue_100199::struct_with_bound]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in the crate root
+   |
+   = note: this error originates in the attribute macro `issue_100199::struct_with_bound` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider importing this trait
+   |
+LL | use traits::MyTrait;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0405`.