From f168d97c49de007d4258398a03d2d710d71fef06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 25 Apr 2019 18:37:21 -0700 Subject: [PATCH] Elide unused import errors for failed use statements --- src/librustc_resolve/check_unused.rs | 26 +++++++++++++++++++++-- src/librustc_resolve/lib.rs | 2 ++ src/librustc_resolve/resolve_imports.rs | 10 ++++++--- src/test/ui/imports/failed-imports.rs | 12 +++++++++++ src/test/ui/imports/failed-imports.stderr | 22 +++++++++++++++++++ 5 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/imports/failed-imports.rs create mode 100644 src/test/ui/imports/failed-imports.stderr diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 3b6179f78558b..4188306efc2db 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -26,7 +26,7 @@ use std::ops::{Deref, DerefMut}; use crate::Resolver; -use crate::resolve_imports::ImportDirectiveSubclass; +use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass}; use rustc::util::nodemap::NodeMap; use rustc::{lint, ty}; @@ -283,7 +283,15 @@ pub fn check_crate(resolver: &mut Resolver<'_>, krate: &ast::Crate) { }; visit::walk_crate(&mut visitor, krate); - for unused in visitor.unused_imports.values() { + let mut silencing_spans: Vec = visitor.privacy_errors + .iter() + .map(|crate::PrivacyError(span, _, _)| span) + .chain(visitor.indeterminate_imports.iter().map(|ImportDirective { span, .. }| span)) + .chain(visitor.unresolved_imports.iter()) + .map(|sp| *sp) + .collect(); + + 'unused_imports: for unused in visitor.unused_imports.values() { let mut fixes = Vec::new(); let mut spans = match calc_unused_spans(unused, unused.use_tree, unused.use_tree_id) { UnusedSpanResult::Used => continue, @@ -305,6 +313,20 @@ pub fn check_crate(resolver: &mut Resolver<'_>, krate: &ast::Crate) { let len = spans.len(); spans.sort(); + for sp in &spans { + // Do not emit unused warnings about failed use statements (#48244) + let mut idx = None; + for (i, span) in silencing_spans.iter().enumerate() { + if sp.overlaps(*span) { + idx = Some(i); + break; + } + } + if let Some(idx) = idx { + silencing_spans.remove(idx); // we won't be seeing this again + continue 'unused_imports; + } + } let ms = MultiSpan::from_spans(spans.clone()); let mut span_snippets = spans.iter() .filter_map(|s| { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 7754bb26f9055..50409c36fcc7e 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1555,6 +1555,7 @@ pub struct Resolver<'a> { /// All non-determined imports. indeterminate_imports: Vec<&'a ImportDirective<'a>>, + unresolved_imports: Vec, /// The module that represents the current item scope. current_module: Module<'a>, @@ -1924,6 +1925,7 @@ impl<'a> Resolver<'a> { determined_imports: Vec::new(), indeterminate_imports: Vec::new(), + unresolved_imports: Vec::new(), current_module: graph_root, ribs: PerNS { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 58e0df1cd7ce9..17d9cd9cdff6f 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -635,7 +635,7 @@ impl<'a> Resolver<'a> { /// An error that may be transformed into a diagnostic later. Used to combine multiple unresolved /// import errors within the same use tree into a single diagnostic. #[derive(Debug, Clone)] -struct UnresolvedImportError { +pub struct UnresolvedImportError { span: Span, label: Option, note: Vec, @@ -744,19 +744,23 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { // to avoid generating multiple errors on the same import. if !has_errors { for import in &self.indeterminate_imports { - self.throw_unresolved_import_error(errors, Some(MultiSpan::from(import.span))); + let sp = Some(MultiSpan::from(import.span)); + self.throw_unresolved_import_error(errors, sp); break; } } } fn throw_unresolved_import_error( - &self, + &mut self, errors: Vec<(String, UnresolvedImportError)>, span: Option, ) { /// Upper limit on the number of `span_label` messages. const MAX_LABEL_COUNT: usize = 10; + for (_, error) in &errors { + self.unresolved_imports.push(error.span); + } let (span, msg) = if errors.is_empty() { (span.unwrap(), "unresolved import".to_string()) diff --git a/src/test/ui/imports/failed-imports.rs b/src/test/ui/imports/failed-imports.rs new file mode 100644 index 0000000000000..0b8665eefd965 --- /dev/null +++ b/src/test/ui/imports/failed-imports.rs @@ -0,0 +1,12 @@ +#![deny(unused_imports)] +// there should be *no* unused import errors + +mod qux { + pub(in crate::qux) fn quz() {} +} + +use qux::quz;//~ ERROR function `quz` is private +use qux::bar;//~ ERROR unresolved import `qux::bar` +use foo::bar; //~ ERROR unresolved import `foo` + +fn main() {} diff --git a/src/test/ui/imports/failed-imports.stderr b/src/test/ui/imports/failed-imports.stderr new file mode 100644 index 0000000000000..59c2b6bf1fb55 --- /dev/null +++ b/src/test/ui/imports/failed-imports.stderr @@ -0,0 +1,22 @@ +error[E0432]: unresolved import `qux::bar` + --> $DIR/failed-imports.rs:9:5 + | +LL | use qux::bar; + | ^^^^^^^^ no `bar` in `qux` + +error[E0432]: unresolved import `foo` + --> $DIR/failed-imports.rs:10:5 + | +LL | use foo::bar; + | ^^^ maybe a missing `extern crate foo;`? + +error[E0603]: function `quz` is private + --> $DIR/failed-imports.rs:8:10 + | +LL | use qux::quz; + | ^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0432, E0603. +For more information about an error, try `rustc --explain E0432`.