mirror of
https://github.com/rust-lang/rust
synced 2024-10-01 22:34:35 +00:00
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:
parent
3d0ac7ea23
commit
57967269e9
|
@ -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;
|
||||
|
@ -2480,14 +2484,15 @@ fn show_candidates(
|
|||
("one of these", "items", String::new())
|
||||
};
|
||||
|
||||
let tail = if path.len() > 1 { "..." } else { "" };
|
||||
let instead = if let Instead::Yes = instead { " instead" } else { "" };
|
||||
let mut msg = if let IsPattern::Yes = is_pattern {
|
||||
format!(
|
||||
"if you meant to match on {}{}{}, use the full path in the pattern",
|
||||
kind, instead, name
|
||||
"if you meant to match on {}{}{}, use the full path in the pattern{}",
|
||||
kind, instead, name, tail
|
||||
)
|
||||
} else {
|
||||
format!("consider importing {} {}{}", determiner, kind, instead)
|
||||
format!("consider importing {} {}{}{}", determiner, kind, instead, tail)
|
||||
};
|
||||
|
||||
for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
|
||||
|
@ -2515,6 +2520,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),
|
||||
"...and refer to it directly",
|
||||
String::new(),
|
||||
Applicability::Unspecified,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
msg.push(':');
|
||||
|
||||
|
|
|
@ -2682,6 +2682,7 @@ fn smart_resolve_path_fragment(
|
|||
def_id,
|
||||
instead,
|
||||
suggestion,
|
||||
path: path.into(),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -2745,6 +2746,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)]
|
||||
|
|
|
@ -4,10 +4,15 @@ error[E0425]: cannot find function `bar` in module `a`
|
|||
LL | a::bar();
|
||||
| ^^^ not found in `a`
|
||||
|
|
||||
help: consider importing this function
|
||||
help: consider importing this function...
|
||||
|
|
||||
LL | use b::bar;
|
||||
|
|
||||
help: ...and refer to it directly
|
||||
|
|
||||
LL - a::bar();
|
||||
LL + bar();
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -12,12 +12,17 @@ help: a tuple struct with a similar name exists
|
|||
|
|
||||
LL | check(m1::TS);
|
||||
| ~~
|
||||
help: consider importing one of these items instead
|
||||
help: consider importing one of these items instead...
|
||||
|
|
||||
LL | use m2::S;
|
||||
|
|
||||
LL | use xm2::S;
|
||||
|
|
||||
help: ...and 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
|
||||
|
@ -35,12 +40,17 @@ help: a tuple struct with a similar name exists
|
|||
|
|
||||
LL | check(xm1::TS);
|
||||
| ~~
|
||||
help: consider importing one of these items instead
|
||||
help: consider importing one of these items instead...
|
||||
|
|
||||
LL | use m2::S;
|
||||
|
|
||||
LL | use xm2::S;
|
||||
|
|
||||
help: ...and 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
|
||||
|
@ -61,12 +71,17 @@ help: a tuple variant with a similar name exists
|
|||
|
|
||||
LL | check(m7::TV);
|
||||
| ~~
|
||||
help: consider importing one of these items instead
|
||||
help: consider importing one of these items instead...
|
||||
|
|
||||
LL | use m8::V;
|
||||
|
|
||||
LL | use xm8::V;
|
||||
|
|
||||
help: ...and 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
|
||||
|
@ -89,12 +104,17 @@ help: a tuple variant with a similar name exists
|
|||
|
|
||||
LL | check(xm7::TV);
|
||||
| ~~
|
||||
help: consider importing one of these items instead
|
||||
help: consider importing one of these items instead...
|
||||
|
|
||||
LL | use m8::V;
|
||||
|
|
||||
LL | use xm8::V;
|
||||
|
|
||||
help: ...and 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
|
||||
|
|
|
@ -10,10 +10,15 @@ error[E0425]: cannot find function `hi_str` in module `circular_modules_main`
|
|||
LL | println!("{}", circular_modules_main::hi_str());
|
||||
| ^^^^^^ not found in `circular_modules_main`
|
||||
|
|
||||
help: consider importing this function
|
||||
help: consider importing this function...
|
||||
|
|
||||
LL | use hi_str;
|
||||
|
|
||||
help: ...and refer to it directly
|
||||
|
|
||||
LL - println!("{}", circular_modules_main::hi_str());
|
||||
LL + println!("{}", hi_str());
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -4,10 +4,15 @@ error[E0425]: cannot find value `A` in crate `namespaced_enums`
|
|||
LL | let _ = namespaced_enums::A;
|
||||
| ^ not found in `namespaced_enums`
|
||||
|
|
||||
help: consider importing this unit variant
|
||||
help: consider importing this unit variant...
|
||||
|
|
||||
LL | use namespaced_enums::Foo::A;
|
||||
|
|
||||
help: ...and 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
|
||||
|
@ -15,10 +20,15 @@ error[E0425]: cannot find function, tuple struct or tuple variant `B` in crate `
|
|||
LL | let _ = namespaced_enums::B(10);
|
||||
| ^ not found in `namespaced_enums`
|
||||
|
|
||||
help: consider importing this tuple variant
|
||||
help: consider importing this tuple variant...
|
||||
|
|
||||
LL | use namespaced_enums::Foo::B;
|
||||
|
|
||||
help: ...and 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
|
||||
|
@ -26,10 +36,15 @@ error[E0422]: cannot find struct, variant or union type `C` in crate `namespaced
|
|||
LL | let _ = namespaced_enums::C { a: 10 };
|
||||
| ^ not found in `namespaced_enums`
|
||||
|
|
||||
help: consider importing this variant
|
||||
help: consider importing this variant...
|
||||
|
|
||||
LL | use namespaced_enums::Foo::C;
|
||||
|
|
||||
help: ...and refer to it directly
|
||||
|
|
||||
LL - let _ = namespaced_enums::C { a: 10 };
|
||||
LL + let _ = C { a: 10 };
|
||||
|
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
@ -4,12 +4,17 @@ error[E0425]: cannot find value `LOG10_2` in module `std::f64`
|
|||
LL | const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize;
|
||||
| ^^^^^^^ not found in `std::f64`
|
||||
|
|
||||
help: consider importing one of these items
|
||||
help: consider importing one of these items...
|
||||
|
|
||||
LL | use std::f32::consts::LOG10_2;
|
||||
|
|
||||
LL | use std::f64::consts::LOG10_2;
|
||||
|
|
||||
help: ...and 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
|
||||
|
||||
|
|
|
@ -4,10 +4,15 @@ error[E0433]: failed to resolve: could not find `hahmap` in `std`
|
|||
LL | let _map = std::hahmap::HashMap::new();
|
||||
| ^^^^^^^ not found in `std::hahmap`
|
||||
|
|
||||
help: consider importing this struct
|
||||
help: consider importing this struct...
|
||||
|
|
||||
LL | use std::collections::HashMap;
|
||||
|
|
||||
help: ...and refer to it directly
|
||||
|
|
||||
LL - let _map = std::hahmap::HashMap::new();
|
||||
LL + let _map = HashMap::new();
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -99,12 +99,17 @@ help: a function with a similar name exists
|
|||
|
|
||||
LL | let _: E = m::f;
|
||||
| ~
|
||||
help: consider importing one of these items instead
|
||||
help: consider importing one of these items instead...
|
||||
|
|
||||
LL | use std::f32::consts::E;
|
||||
|
|
||||
LL | use std::f64::consts::E;
|
||||
|
|
||||
help: ...and 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
|
||||
|
|
|
@ -10,10 +10,15 @@ error[E0412]: cannot find type `u8` in the crate root
|
|||
LL | let _: ::u8;
|
||||
| ^^ not found in the crate root
|
||||
|
|
||||
help: consider importing this builtin type
|
||||
help: consider importing this builtin type...
|
||||
|
|
||||
LL | use std::primitive::u8;
|
||||
|
|
||||
help: ...and 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: ...and 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 a new issue