about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs21
-rw-r--r--compiler/rustc_resolve/src/late.rs2
-rw-r--r--compiler/rustc_resolve/src/lib.rs3
-rw-r--r--src/test/ui/macros/macro-outer-attributes.stderr7
-rw-r--r--src/test/ui/namespace/namespace-mix.stderr28
-rw-r--r--src/test/ui/parser/circular_modules_main.stderr7
-rw-r--r--src/test/ui/resolve/enums-are-namespaced-xc.stderr21
-rw-r--r--src/test/ui/resolve/issue-50599.stderr7
-rw-r--r--src/test/ui/resolve/missing-in-namespace.stderr7
-rw-r--r--src/test/ui/resolve/privacy-enum-ctor.stderr7
-rw-r--r--src/test/ui/resolve/resolve-primitive-fallback.stderr7
-rw-r--r--src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.fixed16
-rw-r--r--src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.rs14
-rw-r--r--src/test/ui/trait-bounds/shadowed-path-in-trait-bound-suggestion.stderr19
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`.