diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2022-04-23 16:41:36 -0700 |
|---|---|---|
| committer | Esteban Kuber <esteban@kuber.com.ar> | 2022-05-03 02:00:38 +0000 |
| commit | 57967269e9946945dedd360e8e8654f5dd76ebd1 (patch) | |
| tree | 19a8e48a54cf5ac759a9354027ae8b94e876bf7d | |
| parent | 3d0ac7ea23888438752957eeeb5aa2b73b4fda72 (diff) | |
| download | rust-57967269e9946945dedd360e8e8654f5dd76ebd1.tar.gz rust-57967269e9946945dedd360e8e8654f5dd76ebd1.zip | |
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
| -rw-r--r-- | compiler/rustc_resolve/src/diagnostics.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/lib.rs | 3 | ||||
| -rw-r--r-- | src/test/ui/macros/macro-outer-attributes.stderr | 7 | ||||
| -rw-r--r-- | src/test/ui/namespace/namespace-mix.stderr | 28 | ||||
| -rw-r--r-- | src/test/ui/parser/circular_modules_main.stderr | 7 | ||||
| -rw-r--r-- | src/test/ui/resolve/enums-are-namespaced-xc.stderr | 21 | ||||
| -rw-r--r-- | src/test/ui/resolve/issue-50599.stderr | 7 | ||||
| -rw-r--r-- | src/test/ui/resolve/missing-in-namespace.stderr | 7 | ||||
| -rw-r--r-- | src/test/ui/resolve/privacy-enum-ctor.stderr | 7 | ||||
| -rw-r--r-- | src/test/ui/resolve/resolve-primitive-fallback.stderr | 7 | ||||
| -rw-r--r-- | src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.fixed | 16 | ||||
| -rw-r--r-- | src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.rs | 14 | ||||
| -rw-r--r-- | src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr | 19 |
14 files changed, 149 insertions, 17 deletions
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index aef9fb57a6a..f75ea583d85 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -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 @@ impl<'a> Resolver<'a> { 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 @@ impl<'a> Resolver<'a> { Instead::No, FoundUse::Yes, IsPattern::Yes, + vec![], ); } err @@ -1482,6 +1484,7 @@ impl<'a> Resolver<'a> { 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(':'); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index b89b9c376af..21c9461a83d 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2682,6 +2682,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { def_id, instead, suggestion, + path: path.into(), }); } @@ -2745,6 +2746,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { def_id, instead: false, suggestion: None, + path: path.into(), }); } else { err.cancel(); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index f6109b1dc1a..ff11aba49d8 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -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)] diff --git a/src/test/ui/macros/macro-outer-attributes.stderr b/src/test/ui/macros/macro-outer-attributes.stderr index 8e064d980af..a9fb79b7b27 100644 --- a/src/test/ui/macros/macro-outer-attributes.stderr +++ b/src/test/ui/macros/macro-outer-attributes.stderr @@ -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 diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr index b6108572292..dd9c969fc82 100644 --- a/src/test/ui/namespace/namespace-mix.stderr +++ b/src/test/ui/namespace/namespace-mix.stderr @@ -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 diff --git a/src/test/ui/parser/circular_modules_main.stderr b/src/test/ui/parser/circular_modules_main.stderr index ee45f65a3bd..f6f3babc2d5 100644 --- a/src/test/ui/parser/circular_modules_main.stderr +++ b/src/test/ui/parser/circular_modules_main.stderr @@ -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 diff --git a/src/test/ui/resolve/enums-are-namespaced-xc.stderr b/src/test/ui/resolve/enums-are-namespaced-xc.stderr index 621686dd292..f501683ebc9 100644 --- a/src/test/ui/resolve/enums-are-namespaced-xc.stderr +++ b/src/test/ui/resolve/enums-are-namespaced-xc.stderr @@ -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 diff --git a/src/test/ui/resolve/issue-50599.stderr b/src/test/ui/resolve/issue-50599.stderr index 7ec567a06f0..ef0b30d98d8 100644 --- a/src/test/ui/resolve/issue-50599.stderr +++ b/src/test/ui/resolve/issue-50599.stderr @@ -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 diff --git a/src/test/ui/resolve/missing-in-namespace.stderr b/src/test/ui/resolve/missing-in-namespace.stderr index 8b292aeda50..265f370494a 100644 --- a/src/test/ui/resolve/missing-in-namespace.stderr +++ b/src/test/ui/resolve/missing-in-namespace.stderr @@ -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 diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index c93ba915efb..4ac18c0e795 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -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 diff --git a/src/test/ui/resolve/resolve-primitive-fallback.stderr b/src/test/ui/resolve/resolve-primitive-fallback.stderr index 44631f954df..3db3706ecf5 100644 --- a/src/test/ui/resolve/resolve-primitive-fallback.stderr +++ b/src/test/ui/resolve/resolve-primitive-fallback.stderr @@ -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 diff --git a/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.fixed b/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.fixed new file mode 100644 index 00000000000..39e90d7a3f7 --- /dev/null +++ b/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.fixed @@ -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); +} diff --git a/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.rs b/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.rs new file mode 100644 index 00000000000..ee6ed0cae67 --- /dev/null +++ b/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.rs @@ -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); +} diff --git a/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr b/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr new file mode 100644 index 00000000000..413a0c8d60e --- /dev/null +++ b/src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr @@ -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`. |
