about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-01-11 06:40:58 +0000
committerbors <bors@rust-lang.org>2016-01-11 06:40:58 +0000
commit69e1f57dfbd32a1a342d696a3e79624da97ebe1b (patch)
tree42571100253fd85695b9a256399e9476c2974253
parentd70ab2bdf16c22b9f3ff0230089b44855e3f1593 (diff)
parent834fb17e9476204dbd5723cd2cc3617bf848b9e9 (diff)
downloadrust-69e1f57dfbd32a1a342d696a3e79624da97ebe1b.tar.gz
rust-69e1f57dfbd32a1a342d696a3e79624da97ebe1b.zip
Auto merge of #30295 - jseyfried:fix_extern_crate_duplicate, r=nrc
Fix a bug allowing an item and an external crate to collide so long as the external crate is declared after the item. For example,
```rust
mod core { pub fn f() {} } // This would be an error if it followed the `extern crate`
extern crate core; // This declaration is shadowed by the preceding module

fn main() { core::f(); }
```
This is a [breaking-change], but it looks unlikely to cause breakage in practice, and any breakage can be fixed by removing colliding `extern crate` declarations, which are shadowed and hence unused.
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs2
-rw-r--r--src/librustc_resolve/lib.rs33
2 files changed, 22 insertions, 13 deletions
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 1d3f2b79844..8ed47300a17 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -325,7 +325,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
 
                     debug!("(build reduced graph for item) found extern `{}`",
                            module_to_string(&*external_module));
-                    self.check_for_conflicts_between_external_crates(&**parent, name, sp);
+                    self.check_for_conflicts_for_external_crate(&parent, name, sp);
                     parent.external_module_children
                           .borrow_mut()
                           .insert(name, external_module.clone());
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index a5a22fd7f39..c7031f72af4 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -122,6 +122,8 @@ enum SuggestionType {
 }
 
 pub enum ResolutionError<'a> {
+    /// error E0260: name conflicts with an extern crate
+    NameConflictsWithExternCrate(Name),
     /// error E0401: can't use type parameters from outer function
     TypeParametersFromOuterFunction,
     /// error E0402: cannot use an outer type parameter in this context
@@ -228,6 +230,14 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
     }
 
     match resolution_error {
+        ResolutionError::NameConflictsWithExternCrate(name) => {
+            struct_span_err!(resolver.session,
+                             span,
+                             E0260,
+                             "the name `{}` conflicts with an external crate \
+                             that has been imported into this module",
+                             name)
+        }
         ResolutionError::TypeParametersFromOuterFunction => {
             struct_span_err!(resolver.session,
                              span,
@@ -1297,12 +1307,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
     }
 
-    /// Checks that the names of external crates don't collide with other
-    /// external crates.
-    fn check_for_conflicts_between_external_crates(&self,
-                                                   module: &Module,
-                                                   name: Name,
-                                                   span: Span) {
+    /// Check that an external crate doesn't collide with items or other external crates.
+    fn check_for_conflicts_for_external_crate(&self, module: &Module, name: Name, span: Span) {
         if module.external_module_children.borrow().contains_key(&name) {
             span_err!(self.session,
                       span,
@@ -1310,6 +1316,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                       "an external crate named `{}` has already been imported into this module",
                       name);
         }
+        match module.children.borrow().get(&name) {
+            Some(name_bindings) if name_bindings.type_ns.defined() => {
+                resolve_error(self,
+                              name_bindings.type_ns.span().unwrap_or(codemap::DUMMY_SP),
+                              ResolutionError::NameConflictsWithExternCrate(name));
+            }
+            _ => {},
+        }
     }
 
     /// Checks that the names of items don't collide with external crates.
@@ -1318,12 +1332,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                                              name: Name,
                                                              span: Span) {
         if module.external_module_children.borrow().contains_key(&name) {
-            span_err!(self.session,
-                      span,
-                      E0260,
-                      "the name `{}` conflicts with an external crate that has been imported \
-                       into this module",
-                      name);
+            resolve_error(self, span, ResolutionError::NameConflictsWithExternCrate(name));
         }
     }