diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 3d9380a3ebd..f44eb1aae3e 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -536,6 +536,7 @@ pub(crate) fn finalize_imports(&mut self) { let determined_imports = mem::take(&mut self.determined_imports); let indeterminate_imports = mem::take(&mut self.indeterminate_imports); + let mut glob_error = false; for (is_indeterminate, import) in determined_imports .iter() .map(|i| (false, i)) @@ -547,6 +548,8 @@ pub(crate) fn finalize_imports(&mut self) { self.import_dummy_binding(*import, is_indeterminate); if let Some(err) = unresolved_import_error { + glob_error |= import.is_glob(); + if let ImportKind::Single { source, ref source_bindings, .. } = import.kind { if source.name == kw::SelfLower { // Silence `unresolved import` error if E0429 is already emitted @@ -562,7 +565,7 @@ pub(crate) fn finalize_imports(&mut self) { { // In the case of a new import line, throw a diagnostic message // for the previous line. - self.throw_unresolved_import_error(errors); + self.throw_unresolved_import_error(errors, glob_error); errors = vec![]; } if seen_spans.insert(err.span) { @@ -573,7 +576,7 @@ pub(crate) fn finalize_imports(&mut self) { } if !errors.is_empty() { - self.throw_unresolved_import_error(errors); + self.throw_unresolved_import_error(errors, glob_error); return; } @@ -599,9 +602,7 @@ pub(crate) fn finalize_imports(&mut self) { } } - if !errors.is_empty() { - self.throw_unresolved_import_error(errors); - } + self.throw_unresolved_import_error(errors, glob_error); } pub(crate) fn check_hidden_glob_reexports( @@ -673,7 +674,11 @@ pub(crate) fn check_hidden_glob_reexports( } } - fn throw_unresolved_import_error(&mut self, errors: Vec<(Import<'_>, UnresolvedImportError)>) { + fn throw_unresolved_import_error( + &mut self, + errors: Vec<(Import<'_>, UnresolvedImportError)>, + glob_error: bool, + ) { if errors.is_empty() { return; } @@ -752,7 +757,10 @@ fn throw_unresolved_import_error(&mut self, errors: Vec<(Import<'_>, UnresolvedI } } - diag.emit(); + let guar = diag.emit(); + if glob_error { + self.glob_error = Some(guar); + } } /// Attempts to resolve the given import, returning: diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 322f2922f92..37d9b1a573b 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4039,9 +4039,12 @@ fn report_error(&mut self, span: Span, resolution_error: ResolutionError<'a>) { } #[inline] - /// If we're actually rustdoc then avoid giving a name resolution error for `cfg()` items. + /// If we're actually rustdoc then avoid giving a name resolution error for `cfg()` items or + // an invalid `use foo::*;` was found, which can cause unbounded ammounts of "item not found" + // errors. We silence them all. fn should_report_errs(&self) -> bool { !(self.r.tcx.sess.opts.actually_rustdoc && self.in_func_body) + && !self.r.glob_error.is_some() } // Resolve in alternative namespaces if resolution in the primary namespace fails. diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index af0b4792136..8d4f3c26d95 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -37,7 +37,7 @@ use rustc_data_structures::intern::Interned; use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{FreezeReadGuard, Lrc}; -use rustc_errors::{Applicability, Diag, ErrCode}; +use rustc_errors::{Applicability, Diag, ErrCode, ErrorGuaranteed}; use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind}; use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::def::Namespace::{self, *}; @@ -1052,6 +1052,7 @@ pub struct Resolver<'a, 'tcx> { /// Maps glob imports to the names of items actually imported. glob_map: FxHashMap>, + glob_error: Option, visibilities_for_hashing: Vec<(LocalDefId, ty::Visibility)>, used_imports: FxHashSet, maybe_unused_trait_imports: FxIndexSet, @@ -1421,6 +1422,7 @@ pub fn new( ast_transform_scopes: FxHashMap::default(), glob_map: Default::default(), + glob_error: None, visibilities_for_hashing: Default::default(), used_imports: FxHashSet::default(), maybe_unused_trait_imports: Default::default(), diff --git a/tests/ui/imports/import-from-missing-star-2.rs b/tests/ui/imports/import-from-missing-star-2.rs new file mode 100644 index 00000000000..cb341b0b0ca --- /dev/null +++ b/tests/ui/imports/import-from-missing-star-2.rs @@ -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 +} diff --git a/tests/ui/imports/import-from-missing-star-2.stderr b/tests/ui/imports/import-from-missing-star-2.stderr new file mode 100644 index 00000000000..ea3876248c9 --- /dev/null +++ b/tests/ui/imports/import-from-missing-star-2.stderr @@ -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`. diff --git a/tests/ui/imports/import-from-missing-star-3.rs b/tests/ui/imports/import-from-missing-star-3.rs new file mode 100644 index 00000000000..bec51fd47b3 --- /dev/null +++ b/tests/ui/imports/import-from-missing-star-3.rs @@ -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(); +} diff --git a/tests/ui/imports/import-from-missing-star-3.stderr b/tests/ui/imports/import-from-missing-star-3.stderr new file mode 100644 index 00000000000..1fe5d4f19a9 --- /dev/null +++ b/tests/ui/imports/import-from-missing-star-3.stderr @@ -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`. diff --git a/tests/ui/imports/import-from-missing-star.rs b/tests/ui/imports/import-from-missing-star.rs new file mode 100644 index 00000000000..cb21e16ba67 --- /dev/null +++ b/tests/ui/imports/import-from-missing-star.rs @@ -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(); +} diff --git a/tests/ui/imports/import-from-missing-star.stderr b/tests/ui/imports/import-from-missing-star.stderr new file mode 100644 index 00000000000..f8e29507804 --- /dev/null +++ b/tests/ui/imports/import-from-missing-star.stderr @@ -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`. diff --git a/tests/ui/imports/issue-31212.rs b/tests/ui/imports/issue-31212.rs index 556f0d18f9f..fe69c5af270 100644 --- a/tests/ui/imports/issue-31212.rs +++ b/tests/ui/imports/issue-31212.rs @@ -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 } diff --git a/tests/ui/imports/issue-31212.stderr b/tests/ui/imports/issue-31212.stderr index 0bb56b361cb..5bba791fd02 100644 --- a/tests/ui/imports/issue-31212.stderr +++ b/tests/ui/imports/issue-31212.stderr @@ -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 1 previous error -error: aborting due to 2 previous errors - -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`.