Skip to content

Commit

Permalink
Silence some resolve errors when there have been glob import errors
Browse files Browse the repository at this point in the history
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 #96799.
  • Loading branch information
estebank committed May 21, 2024
1 parent 1a73979 commit fcf866d
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 11 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_resolve/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
self.import_dummy_binding(*import, is_indeterminate);

if let Some(err) = unresolved_import_error {
if let ImportKind::Glob { .. } = import.kind {
self.glob_error = true;
}

if let ImportKind::Single { source, ref source_bindings, .. } = import.kind {
if source.name == kw::SelfLower {
// Silence `unresolved import` error if E0429 is already emitted
Expand Down
21 changes: 20 additions & 1 deletion compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3784,7 +3784,15 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {

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

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

if this.r.glob_error && !path.is_empty() {
// An invalid `use foo::*;` was found, which can cause unbounded ammounts of "item
// not found" errors. We silence them until all cases of these bad glob imports are
// resolved.
this.r.dcx().span_delayed_bug(
path[0].ident.span,
"silenced resolve error due to earlier failed glob import",
);
return None;
}

let (mut err, candidates) = this.smart_resolve_report_errors(
prefix_path,
following_seg,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,7 @@ pub struct Resolver<'a, 'tcx> {

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

glob_map: Default::default(),
glob_error: false,
visibilities_for_hashing: Default::default(),
used_imports: FxHashSet::default(),
maybe_unused_trait_imports: Default::default(),
Expand Down
12 changes: 12 additions & 0 deletions tests/ui/imports/import-from-missing-star-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
mod foo {
use spam::*; //~ ERROR unresolved import `spam` [E0432]
}

fn main() {
// Expect this to pass because the compiler knows there's a failed `*` import in `foo` that
// might have caused it.
foo::bar();
// FIXME: these two should *fail* because they can't be fixed by fixing the glob import in `foo`
ham(); // should error but doesn't
eggs(); // should error but doesn't
}
11 changes: 11 additions & 0 deletions tests/ui/imports/import-from-missing-star-2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error[E0432]: unresolved import `spam`
--> $DIR/import-from-missing-star-2.rs:2:9
|
LL | use spam::*;
| ^^^^ maybe a missing crate `spam`?
|
= help: consider adding `extern crate spam` to use the `spam` crate

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0432`.
43 changes: 43 additions & 0 deletions tests/ui/imports/import-from-missing-star-3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
mod foo {
use spam::*; //~ ERROR unresolved import `spam` [E0432]

fn x() {
// Expect these to pass because the compiler knows there's a failed `*` import that might
// fix it.
eggs();
foo::bar();
}
}

mod bar {
fn z() {}
fn x() {
// Expect these to pass because the compiler knows there's a failed `*` import that might
// fix it.
foo::bar();
z();
// FIXME: should error but doesn't because as soon as there's a single glob import error, we
// silence all resolve errors.
eggs();
}
}

mod baz {
fn x() {
use spam::*; //~ ERROR unresolved import `spam` [E0432]
fn qux() {}
qux();
// Expect this to pass because the compiler knows there's a local failed `*` import that
// might have caused it.
eggs();
// Expect this to pass because the compiler knows there's a failed `*` import in `foo` that
// might have caused it.
foo::bar();
}
}

fn main() {
// FIXME: should error but doesn't because as soon as there's a single glob import error, we
// silence all resolve errors.
ham();
}
19 changes: 19 additions & 0 deletions tests/ui/imports/import-from-missing-star-3.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
error[E0432]: unresolved import `spam`
--> $DIR/import-from-missing-star-3.rs:2:9
|
LL | use spam::*;
| ^^^^ maybe a missing crate `spam`?
|
= help: consider adding `extern crate spam` to use the `spam` crate

error[E0432]: unresolved import `spam`
--> $DIR/import-from-missing-star-3.rs:27:13
|
LL | use spam::*;
| ^^^^ maybe a missing crate `spam`?
|
= help: consider adding `extern crate spam` to use the `spam` crate

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0432`.
10 changes: 10 additions & 0 deletions tests/ui/imports/import-from-missing-star.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use spam::*; //~ ERROR unresolved import `spam` [E0432]

fn main() {
// Expect these to pass because the compiler knows there's a failed `*` import that might have
// caused it.
ham();
eggs();
// Even this case, as we might have expected `spam::foo` to exist.
foo::bar();
}
11 changes: 11 additions & 0 deletions tests/ui/imports/import-from-missing-star.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error[E0432]: unresolved import `spam`
--> $DIR/import-from-missing-star.rs:1:5
|
LL | use spam::*;
| ^^^^ maybe a missing crate `spam`?
|
= help: consider adding `extern crate spam` to use the `spam` crate

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0432`.
2 changes: 1 addition & 1 deletion tests/ui/imports/issue-31212.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ mod foo {
}

fn main() {
foo::f(); //~ ERROR cannot find function `f` in module `foo`
foo::f(); // cannot find function `f` in module `foo`, but silenced
}
11 changes: 2 additions & 9 deletions tests/ui/imports/issue-31212.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,6 @@ error[E0432]: unresolved import `self::*`
LL | pub use self::*;
| ^^^^^^^ cannot glob-import a module into itself

error[E0425]: cannot find function `f` in module `foo`
--> $DIR/issue-31212.rs:9:10
|
LL | foo::f();
| ^ not found in `foo`

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

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

0 comments on commit fcf866d

Please sign in to comment.