diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 0420fa80268..c5b505fba38 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -871,6 +871,7 @@ enum NameBindingKind<'a> { Import { binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>, + used: Cell, }, Ambiguity { b1: &'a NameBinding<'a>, @@ -878,9 +879,15 @@ enum NameBindingKind<'a> { } } -#[derive(Clone, Debug)] struct PrivacyError<'a>(Span, Name, &'a NameBinding<'a>); +struct AmbiguityError<'a> { + span: Span, + name: Name, + b1: &'a NameBinding<'a>, + b2: &'a NameBinding<'a>, +} + impl<'a> NameBinding<'a> { fn module(&self) -> Result, bool /* true if an error has already been reported */> { match self.kind { @@ -938,14 +945,6 @@ impl<'a> NameBinding<'a> { _ => true, } } - - fn ambiguity(&self) -> Option<(&'a NameBinding<'a>, &'a NameBinding<'a>)> { - match self.kind { - NameBindingKind::Ambiguity { b1, b2 } => Some((b1, b2)), - NameBindingKind::Import { binding, .. } => binding.ambiguity(), - _ => None, - } - } } /// Interns the names of the primitive types. @@ -1064,7 +1063,7 @@ pub struct Resolver<'a> { pub maybe_unused_trait_imports: NodeSet, privacy_errors: Vec>, - ambiguity_errors: Vec<(Span, Name, &'a NameBinding<'a>)>, + ambiguity_errors: Vec>, arenas: &'a ResolverArenas<'a>, dummy_binding: &'a NameBinding<'a>, @@ -1276,17 +1275,21 @@ impl<'a> Resolver<'a> { self.used_crates.insert(krate); } - if let NameBindingKind::Import { directive, .. } = binding.kind { - self.used_imports.insert((directive.id, ns)); - self.add_to_glob_map(directive.id, name); + match binding.kind { + NameBindingKind::Import { directive, binding, ref used } if !used.get() => { + used.set(true); + self.used_imports.insert((directive.id, ns)); + self.add_to_glob_map(directive.id, name); + self.record_use(name, ns, binding, span) + } + NameBindingKind::Import { .. } => false, + NameBindingKind::Ambiguity { b1, b2 } => { + let ambiguity_error = AmbiguityError { span: span, name: name, b1: b1, b2: b2 }; + self.ambiguity_errors.push(ambiguity_error); + true + } + _ => false } - - if binding.ambiguity().is_some() { - self.ambiguity_errors.push((span, name, binding)); - return true; - } - - false } fn add_to_glob_map(&mut self, id: NodeId, name: Name) { @@ -3306,9 +3309,8 @@ impl<'a> Resolver<'a> { fn report_errors(&self) { let mut reported_spans = FnvHashSet(); - for &(span, name, binding) in &self.ambiguity_errors { + for &AmbiguityError { span, name, b1, b2 } in &self.ambiguity_errors { if !reported_spans.insert(span) { continue } - let (b1, b2) = binding.ambiguity().unwrap(); let msg1 = format!("`{}` could resolve to the name imported here", name); let msg2 = format!("`{}` could also resolve to the name imported here", name); self.session.struct_span_err(span, &format!("`{}` is ambiguous", name)) diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 875d6745f6b..85c03683c8d 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -308,6 +308,7 @@ impl<'a> Resolver<'a> { kind: NameBindingKind::Import { binding: binding, directive: directive, + used: Cell::new(false), }, span: directive.span, vis: vis, diff --git a/src/test/compile-fail/imports/unused.rs b/src/test/compile-fail/imports/unused.rs new file mode 100644 index 00000000000..4ec9987df42 --- /dev/null +++ b/src/test/compile-fail/imports/unused.rs @@ -0,0 +1,38 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(pub_restricted, item_like_imports)] +#![deny(unused)] + +mod foo { + fn f() {} + + mod m1 { + pub(super) use super::f; //~ ERROR unused + } + + mod m2 { + #[allow(unused)] + use super::m1::*; // (despite this glob import) + } + + mod m3 { + pub(super) use super::f; // Check that this is counted as used (c.f. #36249). + } + + pub mod m4 { + use super::m3::*; + pub fn g() { f(); } + } +} + +fn main() { + foo::m4::g(); +}