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
This commit is contained in:
Dylan DPC 2022-08-09 17:34:55 +05:30 committed by GitHub
commit fac84e8bb6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 6 deletions

View file

@ -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(':');

View file

@ -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> {}
)
}

View file

@ -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() {}

View file

@ -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`.