From 9a561872c419d3bc0c8ac9d13942f73535df27c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 1 Sep 2019 00:01:25 -0700 Subject: [PATCH] Always emit unresolved import errors and hide unused import lint --- src/librustc_resolve/resolve_imports.rs | 89 ++++++++++++------- src/test/ui/extenv/issue-55897.rs | 2 +- src/test/ui/extenv/issue-55897.stderr | 8 +- .../ui/imports/unresolved-imports-used.rs | 8 +- .../ui/imports/unresolved-imports-used.stderr | 26 +++++- .../ui/rust-2018/uniform-paths/deadlock.rs | 2 +- .../rust-2018/uniform-paths/deadlock.stderr | 6 +- 7 files changed, 96 insertions(+), 45 deletions(-) diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 132690dcd7df2..eb509f1a01d67 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -71,7 +71,7 @@ pub enum ImportDirectiveSubclass<'a> { } /// One import directive. -#[derive(Debug,Clone)] +#[derive(Debug, Clone)] crate struct ImportDirective<'a> { /// The ID of the `extern crate`, `UseTree` etc that imported this `ImportDirective`. /// @@ -447,12 +447,13 @@ impl<'a> Resolver<'a> { } // Define the name or return the existing binding if there is a collision. - pub fn try_define(&mut self, - module: Module<'a>, - ident: Ident, - ns: Namespace, - binding: &'a NameBinding<'a>) - -> Result<(), &'a NameBinding<'a>> { + pub fn try_define( + &mut self, + module: Module<'a>, + ident: Ident, + ns: Namespace, + binding: &'a NameBinding<'a>, + ) -> Result<(), &'a NameBinding<'a>> { let res = binding.res(); self.check_reserved_macro_name(ident, res); self.set_binding_parent_module(binding, module); @@ -480,8 +481,11 @@ impl<'a> Resolver<'a> { }; if glob_binding.res() != nonglob_binding.res() && ns == MacroNS && nonglob_binding.expansion != ExpnId::root() { - resolution.binding = Some(this.ambiguity(AmbiguityKind::GlobVsExpanded, - nonglob_binding, glob_binding)); + resolution.binding = Some(this.ambiguity( + AmbiguityKind::GlobVsExpanded, + nonglob_binding, + glob_binding, + )); } else { resolution.binding = Some(nonglob_binding); } @@ -513,9 +517,11 @@ impl<'a> Resolver<'a> { }) } - fn ambiguity(&self, kind: AmbiguityKind, - primary_binding: &'a NameBinding<'a>, secondary_binding: &'a NameBinding<'a>) - -> &'a NameBinding<'a> { + fn ambiguity( + &self, kind: AmbiguityKind, + primary_binding: &'a NameBinding<'a>, + secondary_binding: &'a NameBinding<'a>, + ) -> &'a NameBinding<'a> { self.arenas.alloc_name_binding(NameBinding { ambiguity: Some((secondary_binding, kind)), ..primary_binding.clone() @@ -524,8 +530,12 @@ impl<'a> Resolver<'a> { // Use `f` to mutate the resolution of the name in the module. // If the resolution becomes a success, define it in the module's glob importers. - fn update_resolution(&mut self, module: Module<'a>, ident: Ident, ns: Namespace, f: F) - -> T + fn update_resolution( + &mut self, module: Module<'a>, + ident: Ident, + ns: Namespace, + f: F, + ) -> T where F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> T { // Ensure that `resolution` isn't borrowed when defining in the module's glob importers, @@ -627,14 +637,18 @@ impl<'a, 'b> ImportResolver<'a, 'b> { self.finalize_resolutions_in(module); } - let mut has_errors = false; let mut seen_spans = FxHashSet::default(); let mut errors = vec![]; let mut prev_root_id: NodeId = NodeId::from_u32(0); - for i in 0 .. self.r.determined_imports.len() { - let import = self.r.determined_imports[i]; + let determined_imports = mem::take(&mut self.r.determined_imports); + let indeterminate_imports = mem::take(&mut self.r.indeterminate_imports); + + for (is_indeterminate, import) in determined_imports + .into_iter() + .map(|i| (false, i)) + .chain(indeterminate_imports.into_iter().map(|i| (true, i))) + { if let Some(err) = self.finalize_import(import) { - has_errors = true; if let SingleImport { source, ref source_bindings, .. } = import.subclass { if source.name == kw::SelfLower { @@ -666,25 +680,27 @@ impl<'a, 'b> ImportResolver<'a, 'b> { errors.push((path, err)); prev_root_id = import.root_id; } + } else if is_indeterminate { + // Consider erroneous imports used to avoid duplicate diagnostics. + self.r.used_imports.insert((import.id, TypeNS)); + let path = import_path_to_string( + &import.module_path.iter().map(|seg| seg.ident).collect::>(), + &import.subclass, + import.span, + ); + let err = UnresolvedImportError { + span: import.span, + label: None, + note: Vec::new(), + suggestion: None, + }; + errors.push((path, err)); } } if !errors.is_empty() { self.throw_unresolved_import_error(errors.clone(), None); } - - for import in &self.r.indeterminate_imports { - // Consider erroneous imports used to avoid duplicate diagnostics. - self.r.used_imports.insert((import.id, TypeNS)); - } - // Report unresolved imports only if no hard error was already reported - // to avoid generating multiple errors on the same import. - if !has_errors { - for import in &self.r.indeterminate_imports { - self.throw_unresolved_import_error(errors, Some(MultiSpan::from(import.span))); - break; - } - } } fn throw_unresolved_import_error( @@ -839,8 +855,14 @@ impl<'a, 'b> ImportResolver<'a, 'b> { ) -> Option { let orig_vis = directive.vis.replace(ty::Visibility::Invisible); let prev_ambiguity_errors_len = self.r.ambiguity_errors.len(); - let path_res = self.r.resolve_path(&directive.module_path, None, &directive.parent_scope, - true, directive.span, directive.crate_lint()); + let path_res = self.r.resolve_path( + &directive.module_path, + None, + &directive.parent_scope, + true, + directive.span, + directive.crate_lint(), + ); let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len; directive.vis.set(orig_vis); if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res { @@ -903,7 +925,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } } }; - return Some(err); } return None; diff --git a/src/test/ui/extenv/issue-55897.rs b/src/test/ui/extenv/issue-55897.rs index c3975f6b9255e..64c4107e89875 100644 --- a/src/test/ui/extenv/issue-55897.rs +++ b/src/test/ui/extenv/issue-55897.rs @@ -1,7 +1,7 @@ use prelude::*; //~ ERROR unresolved import `prelude` mod unresolved_env { - use env; + use env; //~ ERROR unresolved import `env` include!(concat!(env!("NON_EXISTENT"), "/data.rs")); //~^ ERROR cannot determine resolution for the macro `env` diff --git a/src/test/ui/extenv/issue-55897.stderr b/src/test/ui/extenv/issue-55897.stderr index 9d68131beabd7..c57a467cdba56 100644 --- a/src/test/ui/extenv/issue-55897.stderr +++ b/src/test/ui/extenv/issue-55897.stderr @@ -19,6 +19,12 @@ LL | use prelude::*; | unresolved import | help: a similar path exists: `std::prelude` +error[E0432]: unresolved import `env` + --> $DIR/issue-55897.rs:4:9 + | +LL | use env; + | ^^^ no `env` in the root + error: cannot determine resolution for the macro `env` --> $DIR/issue-55897.rs:6:22 | @@ -27,6 +33,6 @@ LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); | = note: import resolution is stuck, try simplifying macro imports -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/imports/unresolved-imports-used.rs b/src/test/ui/imports/unresolved-imports-used.rs index 5398dd63c8929..75cf880192c8e 100644 --- a/src/test/ui/imports/unresolved-imports-used.rs +++ b/src/test/ui/imports/unresolved-imports-used.rs @@ -8,11 +8,11 @@ mod qux { use qux::quz; //~ ERROR function `quz` is private use qux::bar; //~ ERROR unresolved import `qux::bar` -use foo::bar; -use baz::*; +use foo::bar; //~ ERROR unresolved import `foo` +use baz::*; //~ ERROR unresolved import `baz` use qux::bar2; //~ ERROR unresolved import `qux::bar2` -use foo2::bar2; -use baz2::*; +use foo2::bar2;//~ ERROR unresolved import `foo2` +use baz2::*; //~ ERROR unresolved import `baz2` use qux::quy; //~ ERROR unused import fn main() {} diff --git a/src/test/ui/imports/unresolved-imports-used.stderr b/src/test/ui/imports/unresolved-imports-used.stderr index c9342d17a49d7..b341e8e059288 100644 --- a/src/test/ui/imports/unresolved-imports-used.stderr +++ b/src/test/ui/imports/unresolved-imports-used.stderr @@ -10,6 +10,30 @@ error[E0432]: unresolved import `qux::bar2` LL | use qux::bar2; | ^^^^^^^^^ no `bar2` in `qux` +error[E0432]: unresolved import `foo` + --> $DIR/unresolved-imports-used.rs:11:5 + | +LL | use foo::bar; + | ^^^ maybe a missing crate `foo`? + +error[E0432]: unresolved import `baz` + --> $DIR/unresolved-imports-used.rs:12:5 + | +LL | use baz::*; + | ^^^ maybe a missing crate `baz`? + +error[E0432]: unresolved import `foo2` + --> $DIR/unresolved-imports-used.rs:14:5 + | +LL | use foo2::bar2; + | ^^^^ maybe a missing crate `foo2`? + +error[E0432]: unresolved import `baz2` + --> $DIR/unresolved-imports-used.rs:15:5 + | +LL | use baz2::*; + | ^^^^ maybe a missing crate `baz2`? + error[E0603]: function `quz` is private --> $DIR/unresolved-imports-used.rs:9:10 | @@ -28,7 +52,7 @@ note: lint level defined here LL | #![deny(unused_imports)] | ^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 8 previous errors Some errors have detailed explanations: E0432, E0603. For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/rust-2018/uniform-paths/deadlock.rs b/src/test/ui/rust-2018/uniform-paths/deadlock.rs index 3228d799083fb..83ed70a0459a8 100644 --- a/src/test/ui/rust-2018/uniform-paths/deadlock.rs +++ b/src/test/ui/rust-2018/uniform-paths/deadlock.rs @@ -1,7 +1,7 @@ // edition:2018 // compile-flags:--extern foo --extern bar -use foo::bar; //~ ERROR unresolved import +use foo::bar; //~ ERROR can't find crate for `foo` use bar::foo; fn main() {} diff --git a/src/test/ui/rust-2018/uniform-paths/deadlock.stderr b/src/test/ui/rust-2018/uniform-paths/deadlock.stderr index b4ac15c588ebd..9336e90afb71d 100644 --- a/src/test/ui/rust-2018/uniform-paths/deadlock.stderr +++ b/src/test/ui/rust-2018/uniform-paths/deadlock.stderr @@ -1,9 +1,9 @@ -error[E0432]: unresolved import +error[E0463]: can't find crate for `foo` --> $DIR/deadlock.rs:4:5 | LL | use foo::bar; - | ^^^^^^^^ + | ^^^ can't find crate error: aborting due to previous error -For more information about this error, try `rustc --explain E0432`. +For more information about this error, try `rustc --explain E0463`.