Auto merge of #96353 - estebank:issue-95413, r=compiler-errors
When suggesting to import an item, also suggest changing the path if appropriate When we don't find an item we search all of them for an appropriate import and suggest `use`ing it. This is sometimes done for expressions that have paths with more than one segment. We now also suggest changing that path to work with the `use`. Fix #95413
This commit is contained in:
commit
9add63257b
@ -117,7 +117,7 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
|
||||
fn report_with_use_injections(&mut self, krate: &Crate) {
|
||||
for UseError { mut err, candidates, def_id, instead, suggestion } in
|
||||
for UseError { mut err, candidates, def_id, instead, suggestion, path } in
|
||||
self.use_injections.drain(..)
|
||||
{
|
||||
let (span, found_use) = if let Some(def_id) = def_id.as_local() {
|
||||
@ -135,6 +135,7 @@ fn report_with_use_injections(&mut self, krate: &Crate) {
|
||||
if instead { Instead::Yes } else { Instead::No },
|
||||
found_use,
|
||||
IsPattern::No,
|
||||
path,
|
||||
);
|
||||
} else if let Some((span, msg, sugg, appl)) = suggestion {
|
||||
err.span_suggestion(span, msg, sugg, appl);
|
||||
@ -702,6 +703,7 @@ fn add_suggestion_for_duplicate_nested_use(
|
||||
Instead::No,
|
||||
FoundUse::Yes,
|
||||
IsPattern::Yes,
|
||||
vec![],
|
||||
);
|
||||
}
|
||||
err
|
||||
@ -1482,6 +1484,7 @@ fn lookup_import_candidates_from_module<FilterFn>(
|
||||
Instead::No,
|
||||
FoundUse::Yes,
|
||||
IsPattern::No,
|
||||
vec![],
|
||||
);
|
||||
|
||||
if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
|
||||
@ -2448,6 +2451,7 @@ fn show_candidates(
|
||||
instead: Instead,
|
||||
found_use: FoundUse,
|
||||
is_pattern: IsPattern,
|
||||
path: Vec<Segment>,
|
||||
) {
|
||||
if candidates.is_empty() {
|
||||
return;
|
||||
@ -2515,6 +2519,14 @@ fn show_candidates(
|
||||
accessible_path_strings.into_iter().map(|a| a.0),
|
||||
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),
|
||||
String::new(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
msg.push(':');
|
||||
|
||||
|
@ -2693,6 +2693,7 @@ fn smart_resolve_path_fragment(
|
||||
def_id,
|
||||
instead,
|
||||
suggestion,
|
||||
path: path.into(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -2756,6 +2757,7 @@ fn smart_resolve_path_fragment(
|
||||
def_id,
|
||||
instead: false,
|
||||
suggestion: None,
|
||||
path: path.into(),
|
||||
});
|
||||
} else {
|
||||
err.cancel();
|
||||
|
@ -696,6 +696,9 @@ struct UseError<'a> {
|
||||
instead: bool,
|
||||
/// Extra free-form suggestion.
|
||||
suggestion: Option<(Span, &'static str, String, Applicability)>,
|
||||
/// Path `Segment`s at the place of use that failed. Used for accurate suggestion after telling
|
||||
/// the user to import the item directly.
|
||||
path: Vec<Segment>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
|
@ -8,6 +8,11 @@ help: consider importing this function
|
||||
|
|
||||
LL | use b::bar;
|
||||
|
|
||||
help: if you import `bar`, refer to it directly
|
||||
|
|
||||
LL - a::bar();
|
||||
LL + bar();
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -18,6 +18,11 @@ LL | use m2::S;
|
||||
|
|
||||
LL | use xm2::S;
|
||||
|
|
||||
help: if you import `S`, refer to it directly
|
||||
|
|
||||
LL - check(m1::S);
|
||||
LL + check(S);
|
||||
|
|
||||
|
||||
error[E0423]: expected value, found type alias `xm1::S`
|
||||
--> $DIR/namespace-mix.rs:40:11
|
||||
@ -41,6 +46,11 @@ LL | use m2::S;
|
||||
|
|
||||
LL | use xm2::S;
|
||||
|
|
||||
help: if you import `S`, refer to it directly
|
||||
|
|
||||
LL - check(xm1::S);
|
||||
LL + check(S);
|
||||
|
|
||||
|
||||
error[E0423]: expected value, found struct variant `m7::V`
|
||||
--> $DIR/namespace-mix.rs:100:11
|
||||
@ -67,6 +77,11 @@ LL | use m8::V;
|
||||
|
|
||||
LL | use xm8::V;
|
||||
|
|
||||
help: if you import `V`, refer to it directly
|
||||
|
|
||||
LL - check(m7::V);
|
||||
LL + check(V);
|
||||
|
|
||||
|
||||
error[E0423]: expected value, found struct variant `xm7::V`
|
||||
--> $DIR/namespace-mix.rs:106:11
|
||||
@ -95,6 +110,11 @@ LL | use m8::V;
|
||||
|
|
||||
LL | use xm8::V;
|
||||
|
|
||||
help: if you import `V`, refer to it directly
|
||||
|
|
||||
LL - check(xm7::V);
|
||||
LL + check(V);
|
||||
|
|
||||
|
||||
error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
|
||||
--> $DIR/namespace-mix.rs:33:11
|
||||
|
@ -14,6 +14,11 @@ help: consider importing this function
|
||||
|
|
||||
LL | use hi_str;
|
||||
|
|
||||
help: if you import `hi_str`, refer to it directly
|
||||
|
|
||||
LL - println!("{}", circular_modules_main::hi_str());
|
||||
LL + println!("{}", hi_str());
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -8,6 +8,11 @@ help: consider importing this unit variant
|
||||
|
|
||||
LL | use namespaced_enums::Foo::A;
|
||||
|
|
||||
help: if you import `A`, refer to it directly
|
||||
|
|
||||
LL - let _ = namespaced_enums::A;
|
||||
LL + let _ = A;
|
||||
|
|
||||
|
||||
error[E0425]: cannot find function, tuple struct or tuple variant `B` in crate `namespaced_enums`
|
||||
--> $DIR/enums-are-namespaced-xc.rs:7:31
|
||||
@ -19,6 +24,11 @@ help: consider importing this tuple variant
|
||||
|
|
||||
LL | use namespaced_enums::Foo::B;
|
||||
|
|
||||
help: if you import `B`, refer to it directly
|
||||
|
|
||||
LL - let _ = namespaced_enums::B(10);
|
||||
LL + let _ = B(10);
|
||||
|
|
||||
|
||||
error[E0422]: cannot find struct, variant or union type `C` in crate `namespaced_enums`
|
||||
--> $DIR/enums-are-namespaced-xc.rs:9:31
|
||||
@ -30,6 +40,11 @@ help: consider importing this variant
|
||||
|
|
||||
LL | use namespaced_enums::Foo::C;
|
||||
|
|
||||
help: if you import `C`, refer to it directly
|
||||
|
|
||||
LL - let _ = namespaced_enums::C { a: 10 };
|
||||
LL + let _ = C { a: 10 };
|
||||
|
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -10,6 +10,11 @@ LL | use std::f32::consts::LOG10_2;
|
||||
|
|
||||
LL | use std::f64::consts::LOG10_2;
|
||||
|
|
||||
help: if you import `LOG10_2`, refer to it directly
|
||||
|
|
||||
LL - const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize;
|
||||
LL + const M: usize = (f64::from(N) * LOG10_2) as usize;
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -8,6 +8,11 @@ help: consider importing this struct
|
||||
|
|
||||
LL | use std::collections::HashMap;
|
||||
|
|
||||
help: if you import `HashMap`, refer to it directly
|
||||
|
|
||||
LL - let _map = std::hahmap::HashMap::new();
|
||||
LL + let _map = HashMap::new();
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -105,6 +105,11 @@ LL | use std::f32::consts::E;
|
||||
|
|
||||
LL | use std::f64::consts::E;
|
||||
|
|
||||
help: if you import `E`, refer to it directly
|
||||
|
|
||||
LL - let _: E = m::E;
|
||||
LL + let _: E = E;
|
||||
|
|
||||
|
||||
error[E0423]: expected value, found struct variant `m::E::Struct`
|
||||
--> $DIR/privacy-enum-ctor.rs:45:16
|
||||
|
@ -14,6 +14,11 @@ help: consider importing this builtin type
|
||||
|
|
||||
LL | use std::primitive::u8;
|
||||
|
|
||||
help: if you import `u8`, refer to it directly
|
||||
|
|
||||
LL - let _: ::u8;
|
||||
LL + let _: u8;
|
||||
|
|
||||
|
||||
error[E0061]: this function takes 0 arguments but 1 argument was supplied
|
||||
--> $DIR/resolve-primitive-fallback.rs:3:5
|
||||
|
@ -0,0 +1,16 @@
|
||||
// run-rustfix
|
||||
#![allow(non_snake_case)]
|
||||
mod A {
|
||||
pub trait Trait {}
|
||||
impl Trait for i32 {}
|
||||
}
|
||||
|
||||
mod B {
|
||||
use A::Trait;
|
||||
|
||||
pub struct A<H: Trait>(pub H); //~ ERROR cannot find trait
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = B::A(42);
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
// run-rustfix
|
||||
#![allow(non_snake_case)]
|
||||
mod A {
|
||||
pub trait Trait {}
|
||||
impl Trait for i32 {}
|
||||
}
|
||||
|
||||
mod B {
|
||||
pub struct A<H: A::Trait>(pub H); //~ ERROR cannot find trait
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = B::A(42);
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
error[E0405]: cannot find trait `Trait` in `A`
|
||||
--> $DIR/shadowed-path-in-trait-bound-suggestion.rs:9:24
|
||||
|
|
||||
LL | pub struct A<H: A::Trait>(pub H);
|
||||
| ^^^^^ not found in `A`
|
||||
|
|
||||
help: consider importing this trait
|
||||
|
|
||||
LL | use A::Trait;
|
||||
|
|
||||
help: if you import `Trait`, refer to it directly
|
||||
|
|
||||
LL - pub struct A<H: A::Trait>(pub H);
|
||||
LL + pub struct A<H: Trait>(pub H);
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0405`.
|
Loading…
Reference in New Issue
Block a user