]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_resolve/build_reduced_graph.rs
Prohibit macro-expanded `extern crate` items shadowing crates passed with `--extern`
[rust.git] / src / librustc_resolve / build_reduced_graph.rs
index d1a05964c8f6497c0993fc342a40ee201c7e1817..aa7bfeae5f48b034013c64a9e089fb4f80b5e52c 100644 (file)
 //! Here we build the "reduced graph": the graph of the module tree without
 //! any imports resolved.
 
-use macros::{InvocationData, LegacyScope};
+use macros::{InvocationData, ParentScope, LegacyScope};
 use resolve_imports::ImportDirective;
 use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
 use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, ToNameBinding};
-use {ModuleOrUniformRoot, PerNS, Resolver, ResolverArenas};
+use {ModuleOrUniformRoot, PerNS, Resolver, ResolverArenas, ExternPreludeEntry};
 use Namespace::{self, TypeNS, ValueNS, MacroNS};
 use {resolve_error, resolve_struct_error, ResolutionError};
 
 use rustc::hir::def::*;
-use rustc::hir::def_id::{BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
+use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
 use rustc::ty;
 use rustc::middle::cstore::CrateStore;
 use rustc_metadata::cstore::LoadedMacro;
 
 use std::cell::Cell;
+use std::ptr;
 use rustc_data_structures::sync::Lrc;
 
 use syntax::ast::{Name, Ident};
@@ -139,7 +140,7 @@ fn build_reduced_graph_for_use_tree(
 
         let prefix_iter = || parent_prefix.iter().cloned()
             .chain(use_tree.prefix.segments.iter().map(|seg| seg.ident));
-        let prefix_start = prefix_iter().nth(0);
+        let prefix_start = prefix_iter().next();
         let starts_with_non_keyword = prefix_start.map_or(false, |ident| {
             !ident.is_path_segment_keyword()
         });
@@ -437,19 +438,41 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                 let module =
                     self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
                 self.populate_module_if_necessary(module);
-                if injected_crate_name().map_or(false, |name| item.ident.name == name) {
+                if injected_crate_name().map_or(false, |name| ident.name == name) {
                     self.injected_crate = Some(module);
                 }
 
                 let used = self.process_legacy_macro_imports(item, module, expansion);
                 let binding =
                     (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas);
+                if ptr::eq(self.current_module, self.graph_root) {
+                    if let Some(entry) = self.extern_prelude.get(&ident.modern()) {
+                        if expansion != Mark::root() && orig_name.is_some() &&
+                           entry.extern_crate_item.is_none() {
+                            self.session.span_err(item.span, "macro-expanded `extern crate` items \
+                                                              cannot shadow names passed with \
+                                                              `--extern`");
+                        }
+                    }
+                    let entry = self.extern_prelude.entry(ident.modern())
+                                                   .or_insert(ExternPreludeEntry {
+                        extern_crate_item: None,
+                        introduced_by_item: true,
+                    });
+                    entry.extern_crate_item = Some(binding);
+                    if orig_name.is_some() {
+                        entry.introduced_by_item = true;
+                    }
+                }
                 let directive = self.arenas.alloc_import_directive(ImportDirective {
                     root_id: item.id,
                     id: item.id,
                     parent,
                     imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
-                    subclass: ImportDirectiveSubclass::ExternCrate(orig_name),
+                    subclass: ImportDirectiveSubclass::ExternCrate {
+                        source: orig_name,
+                        target: ident,
+                    },
                     root_span: item.span,
                     span: item.span,
                     module_path: Vec::new(),
@@ -465,7 +488,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
 
             ItemKind::GlobalAsm(..) => {}
 
-            ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root
+            ItemKind::Mod(..) if ident == keywords::Invalid.ident() => {} // Crate root
 
             ItemKind::Mod(..) => {
                 let def_id = self.definitions.local_def_id(item.id);
@@ -769,7 +792,7 @@ pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> {
         let def_id = self.macro_defs[&expansion];
         if let Some(id) = self.definitions.as_local_node_id(def_id) {
             self.local_macro_def_scopes[&id]
-        } else if def_id.krate == BUILTIN_MACROS_CRATE {
+        } else if def_id.krate == CrateNum::BuiltinMacros {
             self.injected_crate.unwrap_or(self.graph_root)
         } else {
             let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
@@ -1048,21 +1071,25 @@ fn visit_trait_item(&mut self, item: &'a TraitItem) {
 
     fn visit_token(&mut self, t: Token) {
         if let Token::Interpolated(nt) = t {
-            match nt.0 {
-                token::NtExpr(ref expr) => {
-                    if let ast::ExprKind::Mac(..) = expr.node {
-                        self.visit_invoc(expr.id);
-                    }
+            if let token::NtExpr(ref expr) = nt.0 {
+                if let ast::ExprKind::Mac(..) = expr.node {
+                    self.visit_invoc(expr.id);
                 }
-                _ => {}
             }
         }
     }
 
     fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
         if !attr.is_sugared_doc && is_builtin_attr(attr) {
-            self.resolver.current_module.builtin_attrs.borrow_mut().push((
-                attr.path.segments[0].ident, self.expansion, self.current_legacy_scope
+            let parent_scope = ParentScope {
+                module: self.resolver.current_module.nearest_item_scope(),
+                expansion: self.expansion,
+                legacy: self.current_legacy_scope,
+                // Let's hope discerning built-in attributes from derive helpers is not necessary
+                derives: Vec::new(),
+            };
+            parent_scope.module.builtin_attrs.borrow_mut().push((
+                attr.path.segments[0].ident, parent_scope
             ));
         }
         visit::walk_attribute(self, attr);