about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-09-06 01:44:13 -0700
committerGitHub <noreply@github.com>2016-09-06 01:44:13 -0700
commit5114f8a29ba29c7a168b46ede82fb62d67a2d619 (patch)
tree2cf55f7fc2bf91a05c0d732bb737a24f2631d864
parent1d04201565790e17890f300c2bedeab6b895c313 (diff)
parentff3a6449512e9e6fd1ea455c64cd02a7fa4cc7e2 (diff)
downloadrust-5114f8a29ba29c7a168b46ede82fb62d67a2d619.tar.gz
rust-5114f8a29ba29c7a168b46ede82fb62d67a2d619.zip
Auto merge of #36276 - jseyfried:fix_unused, r=nrc
resolve: Fix unused import false positive with `item_like_imports`

Fixes #36249.
r? @nrc
-rw-r--r--src/librustc_resolve/lib.rs46
-rw-r--r--src/librustc_resolve/resolve_imports.rs1
-rw-r--r--src/test/compile-fail/imports/unused.rs38
3 files changed, 63 insertions, 22 deletions
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<bool>,
     },
     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<Module<'a>, 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<PrivacyError<'a>>,
-    ambiguity_errors: Vec<(Span, Name, &'a NameBinding<'a>)>,
+    ambiguity_errors: Vec<AmbiguityError<'a>>,
 
     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);
-        }
-
-        if binding.ambiguity().is_some() {
-            self.ambiguity_errors.push((span, name, binding));
-            return true;
+        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
         }
-
-        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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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();
+}