about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-10-28 05:17:06 +0000
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-11-10 09:20:55 +0000
commit624a9b73113bdacc6a92d2d2b0704735093fae3c (patch)
tree5f4799f43a4ef2d7d48444afca05831179fa4d53
parentb0e13dc5ba7a8f91ba564c84c62032735bbdc918 (diff)
downloadrust-624a9b73113bdacc6a92d2d2b0704735093fae3c.tar.gz
rust-624a9b73113bdacc6a92d2d2b0704735093fae3c.zip
Avoid building multiple reduced graphs for a crate
that is referenced by multiple `extern crate` items.
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs22
-rw-r--r--src/librustc_resolve/lib.rs2
2 files changed, 15 insertions, 9 deletions
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index ca6e72dd4f4..d987930544e 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -24,7 +24,7 @@ use {resolve_error, resolve_struct_error, ResolutionError};
 
 use rustc::middle::cstore::LoadedMacros;
 use rustc::hir::def::*;
-use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
+use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
 use rustc::ty;
 use rustc::util::nodemap::FxHashMap;
 
@@ -233,14 +233,7 @@ impl<'b> Resolver<'b> {
                 // n.b. we don't need to look at the path option here, because cstore already did
                 let crate_id = self.session.cstore.extern_mod_stmt_cnum(item.id);
                 let module = if let Some(crate_id) = crate_id {
-                    let def_id = DefId {
-                        krate: crate_id,
-                        index: CRATE_DEF_INDEX,
-                    };
-                    let module = self.arenas.alloc_module(ModuleS {
-                        populated: Cell::new(false),
-                        ..ModuleS::new(Some(parent), ModuleKind::Def(Def::Mod(def_id), name))
-                    });
+                    let module = self.get_extern_crate_root(crate_id);
                     let binding = (module, sp, ty::Visibility::Public).to_name_binding();
                     let binding = self.arenas.alloc_name_binding(binding);
                     let directive = self.arenas.alloc_import_directive(ImportDirective {
@@ -504,6 +497,17 @@ impl<'b> Resolver<'b> {
         }
     }
 
+    fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'b> {
+        let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
+        let arenas = self.arenas;
+        *self.extern_crate_roots.entry(cnum).or_insert_with(|| {
+            arenas.alloc_module(ModuleS {
+                populated: Cell::new(false),
+                ..ModuleS::new(None, ModuleKind::Def(Def::Mod(def_id), keywords::Invalid.name()))
+            })
+        })
+    }
+
     /// Ensures that the reduced graph rooted at the given external module
     /// is built, building it if it is not.
     pub fn populate_module_if_necessary(&mut self, module: Module<'b>) {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 4de272bc3a0..b16b61b46b8 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1083,6 +1083,7 @@ pub struct Resolver<'a> {
     // There will be an anonymous module created around `g` with the ID of the
     // entry block for `f`.
     module_map: NodeMap<Module<'a>>,
+    extern_crate_roots: FxHashMap<CrateNum, Module<'a>>,
 
     // Whether or not to print error messages. Can be set to true
     // when getting additional info for error message suggestions,
@@ -1276,6 +1277,7 @@ impl<'a> Resolver<'a> {
             export_map: NodeMap(),
             trait_map: NodeMap(),
             module_map: module_map,
+            extern_crate_roots: FxHashMap(),
 
             emit_errors: true,
             make_glob_map: make_glob_map == MakeGlobMap::Yes,