about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFabian Wolff <fabian.wolff@alumni.ethz.ch>2021-09-11 01:15:40 +0200
committerFabian Wolff <fabian.wolff@alumni.ethz.ch>2021-09-26 18:43:58 +0200
commit65eb381dec051e31d1fb17a5a7629bdee1eb9922 (patch)
tree34e873ef33bc6718a27952e244d7f17b5198bf98
parentac8dd1b2f24dc62c962172b27433106b4e84dc62 (diff)
downloadrust-65eb381dec051e31d1fb17a5a7629bdee1eb9922.tar.gz
rust-65eb381dec051e31d1fb17a5a7629bdee1eb9922.zip
Do not suggest importing inaccessible items
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs85
-rw-r--r--src/test/ui/hygiene/globs.stderr6
-rw-r--r--src/test/ui/imports/glob-resolve1.stderr54
-rw-r--r--src/test/ui/imports/issue-4366-2.stderr6
-rw-r--r--src/test/ui/resolve/issue-42944.stderr6
-rw-r--r--src/test/ui/resolve/issue-88472.rs35
-rw-r--r--src/test/ui/resolve/issue-88472.stderr34
-rw-r--r--src/test/ui/resolve/privacy-enum-ctor.stderr48
-rw-r--r--src/test/ui/resolve/privacy-struct-ctor.stderr6
-rw-r--r--src/test/ui/self/self_type_keyword.stderr6
10 files changed, 165 insertions, 121 deletions
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index d6ff5a7e90b..e75db6f3f00 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1700,41 +1700,72 @@ crate fn show_candidates(
         return;
     }
 
+    let mut accessible_path_strings: Vec<(String, &str)> = Vec::new();
+    let mut inaccessible_path_strings: Vec<(String, &str)> = Vec::new();
+
+    candidates.iter().for_each(|c| {
+        (if c.accessible { &mut accessible_path_strings } else { &mut inaccessible_path_strings })
+            .push((path_names_to_string(&c.path), c.descr))
+    });
+
     // we want consistent results across executions, but candidates are produced
     // by iterating through a hash map, so make sure they are ordered:
-    let mut path_strings: Vec<_> =
-        candidates.iter().map(|c| path_names_to_string(&c.path)).collect();
+    for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] {
+        path_strings.sort();
+        let core_path_strings =
+            path_strings.drain_filter(|p| p.starts_with("core::")).collect::<Vec<String>>();
+        path_strings.extend(core_path_strings);
+        path_strings.dedup();
+    }
 
-    path_strings.sort();
-    let core_path_strings =
-        path_strings.drain_filter(|p| p.starts_with("core::")).collect::<Vec<String>>();
-    path_strings.extend(core_path_strings);
-    path_strings.dedup();
+    if !accessible_path_strings.is_empty() {
+        let (determiner, kind) = if accessible_path_strings.len() == 1 {
+            ("this", accessible_path_strings[0].1)
+        } else {
+            ("one of these", "items")
+        };
 
-    let (determiner, kind) = if candidates.len() == 1 {
-        ("this", candidates[0].descr)
-    } else {
-        ("one of these", "items")
-    };
-
-    let instead = if instead { " instead" } else { "" };
-    let mut msg = format!("consider importing {} {}{}", determiner, kind, instead);
-
-    if let Some(span) = use_placement_span {
-        for candidate in &mut path_strings {
-            // produce an additional newline to separate the new use statement
-            // from the directly following item.
-            let additional_newline = if found_use { "" } else { "\n" };
-            *candidate = format!("use {};\n{}", candidate, additional_newline);
-        }
+        let instead = if instead { " instead" } else { "" };
+        let mut msg = format!("consider importing {} {}{}", determiner, kind, instead);
 
-        err.span_suggestions(span, &msg, path_strings.into_iter(), Applicability::Unspecified);
+        if let Some(span) = use_placement_span {
+            for candidate in &mut accessible_path_strings {
+                // produce an additional newline to separate the new use statement
+                // from the directly following item.
+                let additional_newline = if found_use { "" } else { "\n" };
+                candidate.0 = format!("use {};\n{}", &candidate.0, additional_newline);
+            }
+
+            err.span_suggestions(
+                span,
+                &msg,
+                accessible_path_strings.into_iter().map(|a| a.0),
+                Applicability::Unspecified,
+            );
+        } else {
+            msg.push(':');
+
+            for candidate in accessible_path_strings {
+                msg.push('\n');
+                msg.push_str(&candidate.0);
+            }
+
+            err.note(&msg);
+        }
     } else {
-        msg.push(':');
+        assert!(!inaccessible_path_strings.is_empty());
+
+        let (determiner, kind, verb1, verb2) = if inaccessible_path_strings.len() == 1 {
+            ("this", inaccessible_path_strings[0].1, "exists", "is")
+        } else {
+            ("these", "items", "exist", "are")
+        };
+
+        let mut msg = format!("{} {} {} but {} inaccessible:", determiner, kind, verb1, verb2);
 
-        for candidate in path_strings {
+        for candidate in inaccessible_path_strings {
             msg.push('\n');
-            msg.push_str(&candidate);
+            msg.push_str(&candidate.0);
         }
 
         err.note(&msg);
diff --git a/src/test/ui/hygiene/globs.stderr b/src/test/ui/hygiene/globs.stderr
index c2497f8ff74..6c8b707b8e2 100644
--- a/src/test/ui/hygiene/globs.stderr
+++ b/src/test/ui/hygiene/globs.stderr
@@ -4,7 +4,7 @@ error[E0425]: cannot find function `f` in this scope
 LL |         f();
    |         ^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this function
    |
 LL | use foo::f;
    |
@@ -37,7 +37,7 @@ LL | n!(f);
 LL |         n!(f);
    |            ^ not found in this scope
    |
-   = note: consider importing one of these items:
+   = note: consider importing this function:
            foo::f
    = note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info)
 
@@ -50,7 +50,7 @@ LL | n!(f);
 LL |                 f
    |                 ^ not found in this scope
    |
-   = note: consider importing one of these items:
+   = note: consider importing this function:
            foo::f
    = note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/imports/glob-resolve1.stderr b/src/test/ui/imports/glob-resolve1.stderr
index 2c7a8ad5c1a..3e23c278d66 100644
--- a/src/test/ui/imports/glob-resolve1.stderr
+++ b/src/test/ui/imports/glob-resolve1.stderr
@@ -4,10 +4,8 @@ error[E0425]: cannot find function `fpriv` in this scope
 LL |     fpriv();
    |     ^^^^^ not found in this scope
    |
-help: consider importing this function
-   |
-LL | use bar::fpriv;
-   |
+   = note: this function exists but is inaccessible:
+           bar::fpriv
 
 error[E0425]: cannot find function `epriv` in this scope
   --> $DIR/glob-resolve1.rs:27:5
@@ -15,10 +13,8 @@ error[E0425]: cannot find function `epriv` in this scope
 LL |     epriv();
    |     ^^^^^ not found in this scope
    |
-help: consider importing this function
-   |
-LL | use bar::epriv;
-   |
+   = note: this function exists but is inaccessible:
+           bar::epriv
 
 error[E0423]: expected value, found enum `B`
   --> $DIR/glob-resolve1.rs:28:5
@@ -44,10 +40,8 @@ error[E0425]: cannot find value `C` in this scope
 LL |     C;
    |     ^ not found in this scope
    |
-help: consider importing this unit struct
-   |
-LL | use bar::C;
-   |
+   = note: this unit struct exists but is inaccessible:
+           bar::C
 
 error[E0425]: cannot find function `import` in this scope
   --> $DIR/glob-resolve1.rs:30:5
@@ -67,16 +61,10 @@ LL |     pub enum B {
    |     ---------- similarly named enum `B` defined here
 ...
 LL |     foo::<A>();
-   |           ^
-   |
-help: an enum with a similar name exists
-   |
-LL |     foo::<B>();
-   |           ~
-help: consider importing this enum
-   |
-LL | use bar::A;
+   |           ^ help: an enum with a similar name exists: `B`
    |
+   = note: this enum exists but is inaccessible:
+           bar::A
 
 error[E0412]: cannot find type `C` in this scope
   --> $DIR/glob-resolve1.rs:33:11
@@ -85,16 +73,10 @@ LL |     pub enum B {
    |     ---------- similarly named enum `B` defined here
 ...
 LL |     foo::<C>();
-   |           ^
-   |
-help: an enum with a similar name exists
-   |
-LL |     foo::<B>();
-   |           ~
-help: consider importing this struct
-   |
-LL | use bar::C;
+   |           ^ help: an enum with a similar name exists: `B`
    |
+   = note: this struct exists but is inaccessible:
+           bar::C
 
 error[E0412]: cannot find type `D` in this scope
   --> $DIR/glob-resolve1.rs:34:11
@@ -103,16 +85,10 @@ LL |     pub enum B {
    |     ---------- similarly named enum `B` defined here
 ...
 LL |     foo::<D>();
-   |           ^
-   |
-help: an enum with a similar name exists
-   |
-LL |     foo::<B>();
-   |           ~
-help: consider importing this type alias
-   |
-LL | use bar::D;
+   |           ^ help: an enum with a similar name exists: `B`
    |
+   = note: this type alias exists but is inaccessible:
+           bar::D
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/imports/issue-4366-2.stderr b/src/test/ui/imports/issue-4366-2.stderr
index a86ec7fabea..225104d0dde 100644
--- a/src/test/ui/imports/issue-4366-2.stderr
+++ b/src/test/ui/imports/issue-4366-2.stderr
@@ -4,10 +4,8 @@ error[E0412]: cannot find type `Bar` in this scope
 LL |         fn sub() -> Bar { 1 }
    |                     ^^^ not found in this scope
    |
-help: consider importing this type alias
-   |
-LL |         use a::b::Bar;
-   |
+   = note: this type alias exists but is inaccessible:
+           a::b::Bar
 
 error[E0423]: expected function, found module `foo`
   --> $DIR/issue-4366-2.rs:25:5
diff --git a/src/test/ui/resolve/issue-42944.stderr b/src/test/ui/resolve/issue-42944.stderr
index 008492529d1..1ca7a6d34f7 100644
--- a/src/test/ui/resolve/issue-42944.stderr
+++ b/src/test/ui/resolve/issue-42944.stderr
@@ -16,10 +16,8 @@ error[E0425]: cannot find function, tuple struct or tuple variant `Bx` in this s
 LL |         Bx(());
    |         ^^ not found in this scope
    |
-help: consider importing this tuple struct
-   |
-LL |     use foo::Bx;
-   |
+   = note: this tuple struct exists but is inaccessible:
+           foo::Bx
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/resolve/issue-88472.rs b/src/test/ui/resolve/issue-88472.rs
new file mode 100644
index 00000000000..53cfec57466
--- /dev/null
+++ b/src/test/ui/resolve/issue-88472.rs
@@ -0,0 +1,35 @@
+// Regression test for #88472, where a suggestion was issued to
+// import an inaccessible struct.
+
+#![warn(unused_imports)]
+//~^ NOTE: the lint level is defined here
+
+mod a {
+    struct Foo;
+}
+
+mod b {
+    use crate::a::*;
+    //~^ WARNING: unused import
+    type Bar = Foo;
+    //~^ ERROR: cannot find type `Foo` in this scope [E0412]
+    //~| NOTE: not found in this scope
+    //~| NOTE: this struct exists but is inaccessible
+}
+
+mod c {
+    enum Eee {}
+
+    mod d {
+        enum Eee {}
+    }
+}
+
+mod e {
+    type Baz = Eee;
+    //~^ ERROR: cannot find type `Eee` in this scope [E0412]
+    //~| NOTE: not found in this scope
+    //~| NOTE: these items exist but are inaccessible
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-88472.stderr b/src/test/ui/resolve/issue-88472.stderr
new file mode 100644
index 00000000000..6846210b302
--- /dev/null
+++ b/src/test/ui/resolve/issue-88472.stderr
@@ -0,0 +1,34 @@
+error[E0412]: cannot find type `Foo` in this scope
+  --> $DIR/issue-88472.rs:14:16
+   |
+LL |     type Bar = Foo;
+   |                ^^^ not found in this scope
+   |
+   = note: this struct exists but is inaccessible:
+           a::Foo
+
+error[E0412]: cannot find type `Eee` in this scope
+  --> $DIR/issue-88472.rs:29:16
+   |
+LL |     type Baz = Eee;
+   |                ^^^ not found in this scope
+   |
+   = note: these items exist but are inaccessible:
+           c::Eee
+           c::d::Eee
+
+warning: unused import: `crate::a::*`
+  --> $DIR/issue-88472.rs:12:9
+   |
+LL |     use crate::a::*;
+   |         ^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-88472.rs:4:9
+   |
+LL | #![warn(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr
index 192349e0faf..e79f953970a 100644
--- a/src/test/ui/resolve/privacy-enum-ctor.stderr
+++ b/src/test/ui/resolve/privacy-enum-ctor.stderr
@@ -169,16 +169,10 @@ LL |     pub enum E {
    |     ---------- similarly named enum `E` defined here
 ...
 LL |     let _: Z = m::n::Z;
-   |            ^
-   |
-help: an enum with a similar name exists
-   |
-LL |     let _: E = m::n::Z;
-   |            ~
-help: consider importing this enum
-   |
-LL | use m::Z;
+   |            ^ help: an enum with a similar name exists: `E`
    |
+   = note: this enum exists but is inaccessible:
+           m::Z
 
 error[E0423]: expected value, found enum `m::n::Z`
   --> $DIR/privacy-enum-ctor.rs:57:16
@@ -215,16 +209,10 @@ LL |     pub enum E {
    |     ---------- similarly named enum `E` defined here
 ...
 LL |     let _: Z = m::n::Z::Fn;
-   |            ^
-   |
-help: an enum with a similar name exists
-   |
-LL |     let _: E = m::n::Z::Fn;
-   |            ~
-help: consider importing this enum
-   |
-LL | use m::Z;
+   |            ^ help: an enum with a similar name exists: `E`
    |
+   = note: this enum exists but is inaccessible:
+           m::Z
 
 error[E0412]: cannot find type `Z` in this scope
   --> $DIR/privacy-enum-ctor.rs:64:12
@@ -233,16 +221,10 @@ LL |     pub enum E {
    |     ---------- similarly named enum `E` defined here
 ...
 LL |     let _: Z = m::n::Z::Struct;
-   |            ^
-   |
-help: an enum with a similar name exists
-   |
-LL |     let _: E = m::n::Z::Struct;
-   |            ~
-help: consider importing this enum
-   |
-LL | use m::Z;
+   |            ^ help: an enum with a similar name exists: `E`
    |
+   = note: this enum exists but is inaccessible:
+           m::Z
 
 error[E0423]: expected value, found struct variant `m::n::Z::Struct`
   --> $DIR/privacy-enum-ctor.rs:64:16
@@ -262,16 +244,10 @@ LL |     pub enum E {
    |     ---------- similarly named enum `E` defined here
 ...
 LL |     let _: Z = m::n::Z::Unit {};
-   |            ^
-   |
-help: an enum with a similar name exists
-   |
-LL |     let _: E = m::n::Z::Unit {};
-   |            ~
-help: consider importing this enum
-   |
-LL | use m::Z;
+   |            ^ help: an enum with a similar name exists: `E`
    |
+   = note: this enum exists but is inaccessible:
+           m::Z
 
 error[E0603]: enum `Z` is private
   --> $DIR/privacy-enum-ctor.rs:57:22
diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr
index e5d6f7e9e24..bf1d6753cc1 100644
--- a/src/test/ui/resolve/privacy-struct-ctor.stderr
+++ b/src/test/ui/resolve/privacy-struct-ctor.stderr
@@ -33,10 +33,8 @@ error[E0423]: expected value, found struct `xcrate::S`
 LL |     xcrate::S;
    |     ^^^^^^^^^ constructor is not visible here due to private fields
    |
-help: consider importing this tuple struct instead
-   |
-LL | use m::S;
-   |
+   = note: this tuple struct exists but is inaccessible:
+           m::S
 
 error[E0603]: tuple struct constructor `Z` is private
   --> $DIR/privacy-struct-ctor.rs:18:12
diff --git a/src/test/ui/self/self_type_keyword.stderr b/src/test/ui/self/self_type_keyword.stderr
index 47c04f1eb72..57b46058777 100644
--- a/src/test/ui/self/self_type_keyword.stderr
+++ b/src/test/ui/self/self_type_keyword.stderr
@@ -66,10 +66,8 @@ error[E0531]: cannot find unit struct, unit variant or constant `Self` in this s
 LL |         mut Self => (),
    |             ^^^^ not found in this scope
    |
-help: consider importing this unit struct
-   |
-LL | use foo::Self;
-   |
+   = note: this unit struct exists but is inaccessible:
+           foo::Self
 
 error[E0392]: parameter `'Self` is never used
   --> $DIR/self_type_keyword.rs:6:12