Skip to content

Commit fcf866d

Browse files
committed
Silence some resolve errors when there have been glob import errors
When encountering `use foo::*;` where `foo` fails to be found, and we later encounter resolution errors, we silence those later errors. A single case of the above, for an *existing* import on a big codebase would otherwise have a huge number of knock-down spurious errors. Ideally, instead of a global flag to silence all subsequent resolve errors, we'd want to introduce an unameable binding in the appropriate rib as a sentinel when there's a failed glob import, so when we encounter a resolve error we can search for that sentinel and if found, and only then, silence that error. The current approach is just a quick proof of concept to iterate over. Partially address rust-lang#96799.
1 parent 1a73979 commit fcf866d

11 files changed

+135
-11
lines changed

compiler/rustc_resolve/src/imports.rs

+4
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
547547
self.import_dummy_binding(*import, is_indeterminate);
548548

549549
if let Some(err) = unresolved_import_error {
550+
if let ImportKind::Glob { .. } = import.kind {
551+
self.glob_error = true;
552+
}
553+
550554
if let ImportKind::Single { source, ref source_bindings, .. } = import.kind {
551555
if source.name == kw::SelfLower {
552556
// Silence `unresolved import` error if E0429 is already emitted

compiler/rustc_resolve/src/late.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -3784,7 +3784,15 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
37843784

37853785
let Finalize { node_id, path_span, .. } = finalize;
37863786
let report_errors = |this: &mut Self, res: Option<Res>| {
3787-
if this.should_report_errs() {
3787+
if this.r.glob_error && !path.is_empty() {
3788+
// An invalid `use foo::*;` was found, which can cause unbounded ammounts of "item
3789+
// not found" errors. We silence them until all cases of these bad glob imports are
3790+
// resolved.
3791+
this.r.dcx().span_delayed_bug(
3792+
path[0].ident.span,
3793+
"silenced resolve error due to earlier failed glob import",
3794+
);
3795+
} else if this.should_report_errs() {
37883796
let (err, candidates) =
37893797
this.smart_resolve_report_errors(path, None, path_span, source, res);
37903798

@@ -3845,6 +3853,17 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
38453853
_ => return Some(parent_err),
38463854
};
38473855

3856+
if this.r.glob_error && !path.is_empty() {
3857+
// An invalid `use foo::*;` was found, which can cause unbounded ammounts of "item
3858+
// not found" errors. We silence them until all cases of these bad glob imports are
3859+
// resolved.
3860+
this.r.dcx().span_delayed_bug(
3861+
path[0].ident.span,
3862+
"silenced resolve error due to earlier failed glob import",
3863+
);
3864+
return None;
3865+
}
3866+
38483867
let (mut err, candidates) = this.smart_resolve_report_errors(
38493868
prefix_path,
38503869
following_seg,

compiler/rustc_resolve/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,7 @@ pub struct Resolver<'a, 'tcx> {
10521052

10531053
/// Maps glob imports to the names of items actually imported.
10541054
glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
1055+
glob_error: bool,
10551056
visibilities_for_hashing: Vec<(LocalDefId, ty::Visibility)>,
10561057
used_imports: FxHashSet<NodeId>,
10571058
maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
@@ -1421,6 +1422,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
14211422
ast_transform_scopes: FxHashMap::default(),
14221423

14231424
glob_map: Default::default(),
1425+
glob_error: false,
14241426
visibilities_for_hashing: Default::default(),
14251427
used_imports: FxHashSet::default(),
14261428
maybe_unused_trait_imports: Default::default(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
mod foo {
2+
use spam::*; //~ ERROR unresolved import `spam` [E0432]
3+
}
4+
5+
fn main() {
6+
// Expect this to pass because the compiler knows there's a failed `*` import in `foo` that
7+
// might have caused it.
8+
foo::bar();
9+
// FIXME: these two should *fail* because they can't be fixed by fixing the glob import in `foo`
10+
ham(); // should error but doesn't
11+
eggs(); // should error but doesn't
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0432]: unresolved import `spam`
2+
--> $DIR/import-from-missing-star-2.rs:2:9
3+
|
4+
LL | use spam::*;
5+
| ^^^^ maybe a missing crate `spam`?
6+
|
7+
= help: consider adding `extern crate spam` to use the `spam` crate
8+
9+
error: aborting due to 1 previous error
10+
11+
For more information about this error, try `rustc --explain E0432`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
mod foo {
2+
use spam::*; //~ ERROR unresolved import `spam` [E0432]
3+
4+
fn x() {
5+
// Expect these to pass because the compiler knows there's a failed `*` import that might
6+
// fix it.
7+
eggs();
8+
foo::bar();
9+
}
10+
}
11+
12+
mod bar {
13+
fn z() {}
14+
fn x() {
15+
// Expect these to pass because the compiler knows there's a failed `*` import that might
16+
// fix it.
17+
foo::bar();
18+
z();
19+
// FIXME: should error but doesn't because as soon as there's a single glob import error, we
20+
// silence all resolve errors.
21+
eggs();
22+
}
23+
}
24+
25+
mod baz {
26+
fn x() {
27+
use spam::*; //~ ERROR unresolved import `spam` [E0432]
28+
fn qux() {}
29+
qux();
30+
// Expect this to pass because the compiler knows there's a local failed `*` import that
31+
// might have caused it.
32+
eggs();
33+
// Expect this to pass because the compiler knows there's a failed `*` import in `foo` that
34+
// might have caused it.
35+
foo::bar();
36+
}
37+
}
38+
39+
fn main() {
40+
// FIXME: should error but doesn't because as soon as there's a single glob import error, we
41+
// silence all resolve errors.
42+
ham();
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0432]: unresolved import `spam`
2+
--> $DIR/import-from-missing-star-3.rs:2:9
3+
|
4+
LL | use spam::*;
5+
| ^^^^ maybe a missing crate `spam`?
6+
|
7+
= help: consider adding `extern crate spam` to use the `spam` crate
8+
9+
error[E0432]: unresolved import `spam`
10+
--> $DIR/import-from-missing-star-3.rs:27:13
11+
|
12+
LL | use spam::*;
13+
| ^^^^ maybe a missing crate `spam`?
14+
|
15+
= help: consider adding `extern crate spam` to use the `spam` crate
16+
17+
error: aborting due to 2 previous errors
18+
19+
For more information about this error, try `rustc --explain E0432`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use spam::*; //~ ERROR unresolved import `spam` [E0432]
2+
3+
fn main() {
4+
// Expect these to pass because the compiler knows there's a failed `*` import that might have
5+
// caused it.
6+
ham();
7+
eggs();
8+
// Even this case, as we might have expected `spam::foo` to exist.
9+
foo::bar();
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0432]: unresolved import `spam`
2+
--> $DIR/import-from-missing-star.rs:1:5
3+
|
4+
LL | use spam::*;
5+
| ^^^^ maybe a missing crate `spam`?
6+
|
7+
= help: consider adding `extern crate spam` to use the `spam` crate
8+
9+
error: aborting due to 1 previous error
10+
11+
For more information about this error, try `rustc --explain E0432`.

tests/ui/imports/issue-31212.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ mod foo {
66
}
77

88
fn main() {
9-
foo::f(); //~ ERROR cannot find function `f` in module `foo`
9+
foo::f(); // cannot find function `f` in module `foo`, but silenced
1010
}

tests/ui/imports/issue-31212.stderr

+2-9
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,6 @@ error[E0432]: unresolved import `self::*`
44
LL | pub use self::*;
55
| ^^^^^^^ cannot glob-import a module into itself
66

7-
error[E0425]: cannot find function `f` in module `foo`
8-
--> $DIR/issue-31212.rs:9:10
9-
|
10-
LL | foo::f();
11-
| ^ not found in `foo`
12-
13-
error: aborting due to 2 previous errors
7+
error: aborting due to 1 previous error
148

15-
Some errors have detailed explanations: E0425, E0432.
16-
For more information about an error, try `rustc --explain E0425`.
9+
For more information about this error, try `rustc --explain E0432`.

0 commit comments

Comments
 (0)