Skip to content

Commit 65eb381

Browse files
committed
Do not suggest importing inaccessible items
1 parent ac8dd1b commit 65eb381

10 files changed

+165
-121
lines changed

Diff for: compiler/rustc_resolve/src/diagnostics.rs

+58-27
Original file line numberDiff line numberDiff line change
@@ -1700,41 +1700,72 @@ crate fn show_candidates(
17001700
return;
17011701
}
17021702

1703+
let mut accessible_path_strings: Vec<(String, &str)> = Vec::new();
1704+
let mut inaccessible_path_strings: Vec<(String, &str)> = Vec::new();
1705+
1706+
candidates.iter().for_each(|c| {
1707+
(if c.accessible { &mut accessible_path_strings } else { &mut inaccessible_path_strings })
1708+
.push((path_names_to_string(&c.path), c.descr))
1709+
});
1710+
17031711
// we want consistent results across executions, but candidates are produced
17041712
// by iterating through a hash map, so make sure they are ordered:
1705-
let mut path_strings: Vec<_> =
1706-
candidates.iter().map(|c| path_names_to_string(&c.path)).collect();
1713+
for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] {
1714+
path_strings.sort();
1715+
let core_path_strings =
1716+
path_strings.drain_filter(|p| p.starts_with("core::")).collect::<Vec<String>>();
1717+
path_strings.extend(core_path_strings);
1718+
path_strings.dedup();
1719+
}
17071720

1708-
path_strings.sort();
1709-
let core_path_strings =
1710-
path_strings.drain_filter(|p| p.starts_with("core::")).collect::<Vec<String>>();
1711-
path_strings.extend(core_path_strings);
1712-
path_strings.dedup();
1721+
if !accessible_path_strings.is_empty() {
1722+
let (determiner, kind) = if accessible_path_strings.len() == 1 {
1723+
("this", accessible_path_strings[0].1)
1724+
} else {
1725+
("one of these", "items")
1726+
};
17131727

1714-
let (determiner, kind) = if candidates.len() == 1 {
1715-
("this", candidates[0].descr)
1716-
} else {
1717-
("one of these", "items")
1718-
};
1719-
1720-
let instead = if instead { " instead" } else { "" };
1721-
let mut msg = format!("consider importing {} {}{}", determiner, kind, instead);
1722-
1723-
if let Some(span) = use_placement_span {
1724-
for candidate in &mut path_strings {
1725-
// produce an additional newline to separate the new use statement
1726-
// from the directly following item.
1727-
let additional_newline = if found_use { "" } else { "\n" };
1728-
*candidate = format!("use {};\n{}", candidate, additional_newline);
1729-
}
1728+
let instead = if instead { " instead" } else { "" };
1729+
let mut msg = format!("consider importing {} {}{}", determiner, kind, instead);
17301730

1731-
err.span_suggestions(span, &msg, path_strings.into_iter(), Applicability::Unspecified);
1731+
if let Some(span) = use_placement_span {
1732+
for candidate in &mut accessible_path_strings {
1733+
// produce an additional newline to separate the new use statement
1734+
// from the directly following item.
1735+
let additional_newline = if found_use { "" } else { "\n" };
1736+
candidate.0 = format!("use {};\n{}", &candidate.0, additional_newline);
1737+
}
1738+
1739+
err.span_suggestions(
1740+
span,
1741+
&msg,
1742+
accessible_path_strings.into_iter().map(|a| a.0),
1743+
Applicability::Unspecified,
1744+
);
1745+
} else {
1746+
msg.push(':');
1747+
1748+
for candidate in accessible_path_strings {
1749+
msg.push('\n');
1750+
msg.push_str(&candidate.0);
1751+
}
1752+
1753+
err.note(&msg);
1754+
}
17321755
} else {
1733-
msg.push(':');
1756+
assert!(!inaccessible_path_strings.is_empty());
1757+
1758+
let (determiner, kind, verb1, verb2) = if inaccessible_path_strings.len() == 1 {
1759+
("this", inaccessible_path_strings[0].1, "exists", "is")
1760+
} else {
1761+
("these", "items", "exist", "are")
1762+
};
1763+
1764+
let mut msg = format!("{} {} {} but {} inaccessible:", determiner, kind, verb1, verb2);
17341765

1735-
for candidate in path_strings {
1766+
for candidate in inaccessible_path_strings {
17361767
msg.push('\n');
1737-
msg.push_str(&candidate);
1768+
msg.push_str(&candidate.0);
17381769
}
17391770

17401771
err.note(&msg);

Diff for: src/test/ui/hygiene/globs.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0425]: cannot find function `f` in this scope
44
LL | f();
55
| ^ not found in this scope
66
|
7-
help: consider importing one of these items
7+
help: consider importing this function
88
|
99
LL | use foo::f;
1010
|
@@ -37,7 +37,7 @@ LL | n!(f);
3737
LL | n!(f);
3838
| ^ not found in this scope
3939
|
40-
= note: consider importing one of these items:
40+
= note: consider importing this function:
4141
foo::f
4242
= note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info)
4343

@@ -50,7 +50,7 @@ LL | n!(f);
5050
LL | f
5151
| ^ not found in this scope
5252
|
53-
= note: consider importing one of these items:
53+
= note: consider importing this function:
5454
foo::f
5555
= note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info)
5656

Diff for: src/test/ui/imports/glob-resolve1.stderr

+15-39
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,17 @@ error[E0425]: cannot find function `fpriv` in this scope
44
LL | fpriv();
55
| ^^^^^ not found in this scope
66
|
7-
help: consider importing this function
8-
|
9-
LL | use bar::fpriv;
10-
|
7+
= note: this function exists but is inaccessible:
8+
bar::fpriv
119

1210
error[E0425]: cannot find function `epriv` in this scope
1311
--> $DIR/glob-resolve1.rs:27:5
1412
|
1513
LL | epriv();
1614
| ^^^^^ not found in this scope
1715
|
18-
help: consider importing this function
19-
|
20-
LL | use bar::epriv;
21-
|
16+
= note: this function exists but is inaccessible:
17+
bar::epriv
2218

2319
error[E0423]: expected value, found enum `B`
2420
--> $DIR/glob-resolve1.rs:28:5
@@ -44,10 +40,8 @@ error[E0425]: cannot find value `C` in this scope
4440
LL | C;
4541
| ^ not found in this scope
4642
|
47-
help: consider importing this unit struct
48-
|
49-
LL | use bar::C;
50-
|
43+
= note: this unit struct exists but is inaccessible:
44+
bar::C
5145

5246
error[E0425]: cannot find function `import` in this scope
5347
--> $DIR/glob-resolve1.rs:30:5
@@ -67,16 +61,10 @@ LL | pub enum B {
6761
| ---------- similarly named enum `B` defined here
6862
...
6963
LL | foo::<A>();
70-
| ^
71-
|
72-
help: an enum with a similar name exists
73-
|
74-
LL | foo::<B>();
75-
| ~
76-
help: consider importing this enum
77-
|
78-
LL | use bar::A;
64+
| ^ help: an enum with a similar name exists: `B`
7965
|
66+
= note: this enum exists but is inaccessible:
67+
bar::A
8068

8169
error[E0412]: cannot find type `C` in this scope
8270
--> $DIR/glob-resolve1.rs:33:11
@@ -85,16 +73,10 @@ LL | pub enum B {
8573
| ---------- similarly named enum `B` defined here
8674
...
8775
LL | foo::<C>();
88-
| ^
89-
|
90-
help: an enum with a similar name exists
91-
|
92-
LL | foo::<B>();
93-
| ~
94-
help: consider importing this struct
95-
|
96-
LL | use bar::C;
76+
| ^ help: an enum with a similar name exists: `B`
9777
|
78+
= note: this struct exists but is inaccessible:
79+
bar::C
9880

9981
error[E0412]: cannot find type `D` in this scope
10082
--> $DIR/glob-resolve1.rs:34:11
@@ -103,16 +85,10 @@ LL | pub enum B {
10385
| ---------- similarly named enum `B` defined here
10486
...
10587
LL | foo::<D>();
106-
| ^
107-
|
108-
help: an enum with a similar name exists
109-
|
110-
LL | foo::<B>();
111-
| ~
112-
help: consider importing this type alias
113-
|
114-
LL | use bar::D;
88+
| ^ help: an enum with a similar name exists: `B`
11589
|
90+
= note: this type alias exists but is inaccessible:
91+
bar::D
11692

11793
error: aborting due to 8 previous errors
11894

Diff for: src/test/ui/imports/issue-4366-2.stderr

+2-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@ error[E0412]: cannot find type `Bar` in this scope
44
LL | fn sub() -> Bar { 1 }
55
| ^^^ not found in this scope
66
|
7-
help: consider importing this type alias
8-
|
9-
LL | use a::b::Bar;
10-
|
7+
= note: this type alias exists but is inaccessible:
8+
a::b::Bar
119

1210
error[E0423]: expected function, found module `foo`
1311
--> $DIR/issue-4366-2.rs:25:5

Diff for: src/test/ui/resolve/issue-42944.stderr

+2-4
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@ error[E0425]: cannot find function, tuple struct or tuple variant `Bx` in this s
1616
LL | Bx(());
1717
| ^^ not found in this scope
1818
|
19-
help: consider importing this tuple struct
20-
|
21-
LL | use foo::Bx;
22-
|
19+
= note: this tuple struct exists but is inaccessible:
20+
foo::Bx
2321

2422
error: aborting due to 2 previous errors
2523

Diff for: src/test/ui/resolve/issue-88472.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Regression test for #88472, where a suggestion was issued to
2+
// import an inaccessible struct.
3+
4+
#![warn(unused_imports)]
5+
//~^ NOTE: the lint level is defined here
6+
7+
mod a {
8+
struct Foo;
9+
}
10+
11+
mod b {
12+
use crate::a::*;
13+
//~^ WARNING: unused import
14+
type Bar = Foo;
15+
//~^ ERROR: cannot find type `Foo` in this scope [E0412]
16+
//~| NOTE: not found in this scope
17+
//~| NOTE: this struct exists but is inaccessible
18+
}
19+
20+
mod c {
21+
enum Eee {}
22+
23+
mod d {
24+
enum Eee {}
25+
}
26+
}
27+
28+
mod e {
29+
type Baz = Eee;
30+
//~^ ERROR: cannot find type `Eee` in this scope [E0412]
31+
//~| NOTE: not found in this scope
32+
//~| NOTE: these items exist but are inaccessible
33+
}
34+
35+
fn main() {}

Diff for: src/test/ui/resolve/issue-88472.stderr

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
error[E0412]: cannot find type `Foo` in this scope
2+
--> $DIR/issue-88472.rs:14:16
3+
|
4+
LL | type Bar = Foo;
5+
| ^^^ not found in this scope
6+
|
7+
= note: this struct exists but is inaccessible:
8+
a::Foo
9+
10+
error[E0412]: cannot find type `Eee` in this scope
11+
--> $DIR/issue-88472.rs:29:16
12+
|
13+
LL | type Baz = Eee;
14+
| ^^^ not found in this scope
15+
|
16+
= note: these items exist but are inaccessible:
17+
c::Eee
18+
c::d::Eee
19+
20+
warning: unused import: `crate::a::*`
21+
--> $DIR/issue-88472.rs:12:9
22+
|
23+
LL | use crate::a::*;
24+
| ^^^^^^^^^^^
25+
|
26+
note: the lint level is defined here
27+
--> $DIR/issue-88472.rs:4:9
28+
|
29+
LL | #![warn(unused_imports)]
30+
| ^^^^^^^^^^^^^^
31+
32+
error: aborting due to 2 previous errors; 1 warning emitted
33+
34+
For more information about this error, try `rustc --explain E0412`.

0 commit comments

Comments
 (0)