Rollup merge of #64054 - estebank:unused-import-is-to-eager, r=petrochenkov

Always emit unresolved import errors and hide unused import lint

Fix https://github.com/rust-lang/rust/issues/63724.

r? @petrochenkov
This commit is contained in:
Mazdak Farrokhzad 2019-09-09 22:18:10 +02:00 committed by GitHub
commit 8926301d11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 96 additions and 45 deletions

View File

@ -71,7 +71,7 @@ pub enum ImportDirectiveSubclass<'a> {
} }
/// One import directive. /// One import directive.
#[derive(Debug,Clone)] #[derive(Debug, Clone)]
crate struct ImportDirective<'a> { crate struct ImportDirective<'a> {
/// The ID of the `extern crate`, `UseTree` etc that imported this `ImportDirective`. /// 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. // Define the name or return the existing binding if there is a collision.
pub fn try_define(&mut self, pub fn try_define(
module: Module<'a>, &mut self,
ident: Ident, module: Module<'a>,
ns: Namespace, ident: Ident,
binding: &'a NameBinding<'a>) ns: Namespace,
-> Result<(), &'a NameBinding<'a>> { binding: &'a NameBinding<'a>,
) -> Result<(), &'a NameBinding<'a>> {
let res = binding.res(); let res = binding.res();
self.check_reserved_macro_name(ident, res); self.check_reserved_macro_name(ident, res);
self.set_binding_parent_module(binding, module); self.set_binding_parent_module(binding, module);
@ -480,8 +481,11 @@ impl<'a> Resolver<'a> {
}; };
if glob_binding.res() != nonglob_binding.res() && if glob_binding.res() != nonglob_binding.res() &&
ns == MacroNS && nonglob_binding.expansion != ExpnId::root() { ns == MacroNS && nonglob_binding.expansion != ExpnId::root() {
resolution.binding = Some(this.ambiguity(AmbiguityKind::GlobVsExpanded, resolution.binding = Some(this.ambiguity(
nonglob_binding, glob_binding)); AmbiguityKind::GlobVsExpanded,
nonglob_binding,
glob_binding,
));
} else { } else {
resolution.binding = Some(nonglob_binding); resolution.binding = Some(nonglob_binding);
} }
@ -513,9 +517,11 @@ impl<'a> Resolver<'a> {
}) })
} }
fn ambiguity(&self, kind: AmbiguityKind, fn ambiguity(
primary_binding: &'a NameBinding<'a>, secondary_binding: &'a NameBinding<'a>) &self, kind: AmbiguityKind,
-> &'a NameBinding<'a> { primary_binding: &'a NameBinding<'a>,
secondary_binding: &'a NameBinding<'a>,
) -> &'a NameBinding<'a> {
self.arenas.alloc_name_binding(NameBinding { self.arenas.alloc_name_binding(NameBinding {
ambiguity: Some((secondary_binding, kind)), ambiguity: Some((secondary_binding, kind)),
..primary_binding.clone() ..primary_binding.clone()
@ -524,8 +530,12 @@ impl<'a> Resolver<'a> {
// Use `f` to mutate the resolution of the name in the module. // 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. // If the resolution becomes a success, define it in the module's glob importers.
fn update_resolution<T, F>(&mut self, module: Module<'a>, ident: Ident, ns: Namespace, f: F) fn update_resolution<T, F>(
-> T &mut self, module: Module<'a>,
ident: Ident,
ns: Namespace,
f: F,
) -> T
where F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> 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, // 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); self.finalize_resolutions_in(module);
} }
let mut has_errors = false;
let mut seen_spans = FxHashSet::default(); let mut seen_spans = FxHashSet::default();
let mut errors = vec![]; let mut errors = vec![];
let mut prev_root_id: NodeId = NodeId::from_u32(0); let mut prev_root_id: NodeId = NodeId::from_u32(0);
for i in 0 .. self.r.determined_imports.len() { let determined_imports = mem::take(&mut self.r.determined_imports);
let import = self.r.determined_imports[i]; 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) { if let Some(err) = self.finalize_import(import) {
has_errors = true;
if let SingleImport { source, ref source_bindings, .. } = import.subclass { if let SingleImport { source, ref source_bindings, .. } = import.subclass {
if source.name == kw::SelfLower { if source.name == kw::SelfLower {
@ -666,25 +680,27 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
errors.push((path, err)); errors.push((path, err));
prev_root_id = import.root_id; 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::<Vec<_>>(),
&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() { if !errors.is_empty() {
self.throw_unresolved_import_error(errors.clone(), None); 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( fn throw_unresolved_import_error(
@ -839,8 +855,14 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
) -> Option<UnresolvedImportError> { ) -> Option<UnresolvedImportError> {
let orig_vis = directive.vis.replace(ty::Visibility::Invisible); let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
let prev_ambiguity_errors_len = self.r.ambiguity_errors.len(); let prev_ambiguity_errors_len = self.r.ambiguity_errors.len();
let path_res = self.r.resolve_path(&directive.module_path, None, &directive.parent_scope, let path_res = self.r.resolve_path(
true, directive.span, directive.crate_lint()); &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; let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len;
directive.vis.set(orig_vis); directive.vis.set(orig_vis);
if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res { if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res {
@ -903,7 +925,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
} }
} }
}; };
return Some(err); return Some(err);
} }
return None; return None;

View File

@ -1,7 +1,7 @@
use prelude::*; //~ ERROR unresolved import `prelude` use prelude::*; //~ ERROR unresolved import `prelude`
mod unresolved_env { mod unresolved_env {
use env; use env; //~ ERROR unresolved import `env`
include!(concat!(env!("NON_EXISTENT"), "/data.rs")); include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
//~^ ERROR cannot determine resolution for the macro `env` //~^ ERROR cannot determine resolution for the macro `env`

View File

@ -19,6 +19,12 @@ LL | use prelude::*;
| unresolved import | unresolved import
| help: a similar path exists: `std::prelude` | 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` error: cannot determine resolution for the macro `env`
--> $DIR/issue-55897.rs:6:22 --> $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 = 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`. For more information about this error, try `rustc --explain E0432`.

View File

@ -8,11 +8,11 @@ mod qux {
use qux::quz; //~ ERROR function `quz` is private use qux::quz; //~ ERROR function `quz` is private
use qux::bar; //~ ERROR unresolved import `qux::bar` use qux::bar; //~ ERROR unresolved import `qux::bar`
use foo::bar; use foo::bar; //~ ERROR unresolved import `foo`
use baz::*; use baz::*; //~ ERROR unresolved import `baz`
use qux::bar2; //~ ERROR unresolved import `qux::bar2` use qux::bar2; //~ ERROR unresolved import `qux::bar2`
use foo2::bar2; use foo2::bar2;//~ ERROR unresolved import `foo2`
use baz2::*; use baz2::*; //~ ERROR unresolved import `baz2`
use qux::quy; //~ ERROR unused import use qux::quy; //~ ERROR unused import
fn main() {} fn main() {}

View File

@ -10,6 +10,30 @@ error[E0432]: unresolved import `qux::bar2`
LL | use qux::bar2; LL | use qux::bar2;
| ^^^^^^^^^ no `bar2` in `qux` | ^^^^^^^^^ 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 error[E0603]: function `quz` is private
--> $DIR/unresolved-imports-used.rs:9:10 --> $DIR/unresolved-imports-used.rs:9:10
| |
@ -28,7 +52,7 @@ note: lint level defined here
LL | #![deny(unused_imports)] 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. Some errors have detailed explanations: E0432, E0603.
For more information about an error, try `rustc --explain E0432`. For more information about an error, try `rustc --explain E0432`.

View File

@ -1,7 +1,7 @@
// edition:2018 // edition:2018
// compile-flags:--extern foo --extern bar // 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; use bar::foo;
fn main() {} fn main() {}

View File

@ -1,9 +1,9 @@
error[E0432]: unresolved import error[E0463]: can't find crate for `foo`
--> $DIR/deadlock.rs:4:5 --> $DIR/deadlock.rs:4:5
| |
LL | use foo::bar; LL | use foo::bar;
| ^^^^^^^^ | ^^^ can't find crate
error: aborting due to previous error 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`.