From c99b73a767a38d5b97214b7dbf6ee3c08ac782fd Mon Sep 17 00:00:00 2001
From: Nick Cameron <ncameron@mozilla.com>
Date: Thu, 7 Apr 2016 18:16:12 +1200
Subject: [PATCH 1/9] Trivial refactoring

---
 src/librustc_driver/driver.rs    | 14 +++++++-------
 src/librustc_metadata/creader.rs | 17 ++++++++---------
 2 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index de1a740e0bb..9c444fca9a1 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -766,12 +766,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
          "external crate/lib resolution",
          || LocalCrateReader::new(sess, cstore, &hir_map, name).read_crates());
 
-    let lang_items = time(time_passes, "language item collection", || {
-        sess.track_errors(|| {
-            middle::lang_items::collect_language_items(&sess, &hir_map)
-        })
-    })?;
-
     let resolve::CrateMap {
         def_map,
         freevars,
@@ -779,9 +773,15 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
         trait_map,
         glob_map,
     } = time(time_passes,
-             "resolution",
+             "name resolution",
              || resolve::resolve_crate(sess, &hir_map, make_glob_map));
 
+    let lang_items = time(time_passes, "language item collection", || {
+        sess.track_errors(|| {
+            middle::lang_items::collect_language_items(&sess, &hir_map)
+        })
+    })?;
+
     let mut analysis = ty::CrateAnalysis {
         export_map: export_map,
         access_levels: AccessLevels::default(),
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index df9072835b9..8ec238f4b24 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -813,9 +813,8 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
 
     fn process_crate(&self, c: &hir::Crate) {
         for a in c.attrs.iter().filter(|m| m.name() == "link_args") {
-            match a.value_str() {
-                Some(ref linkarg) => self.cstore.add_used_link_args(&linkarg),
-                None => { /* fallthrough */ }
+            if let Some(ref linkarg) = a.value_str() {
+                self.cstore.add_used_link_args(&linkarg);
             }
         }
     }
@@ -830,12 +829,12 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
                 match self.creader.extract_crate_info_hir(i) {
                     Some(info) => {
                         let (cnum, _, _) = self.creader.resolve_crate(&None,
-                                                                          &info.ident,
-                                                                          &info.name,
-                                                                          None,
-                                                                          i.span,
-                                                                          PathKind::Crate,
-                                                                          true);
+                                                                      &info.ident,
+                                                                      &info.name,
+                                                                      None,
+                                                                      i.span,
+                                                                      PathKind::Crate,
+                                                                      true);
                         let def_id = self.ast_map.local_def_id(i.id);
 
                         let len = self.ast_map.def_path(def_id).data.len();

From f61b40446777f9ef9b32c19d8df24ded855fd082 Mon Sep 17 00:00:00 2001
From: Nick Cameron <ncameron@mozilla.com>
Date: Thu, 14 Apr 2016 11:55:34 +1200
Subject: [PATCH 2/9] Split up NodeCollector so that defs are collected
 separately from nodes for the HIR map.

---
 src/librustc/hir/map/collector.rs | 335 ++++++++++++++++++++----------
 src/librustc/hir/map/mod.rs       |  38 ++--
 src/librustc_driver/driver.rs     |  37 ++--
 3 files changed, 269 insertions(+), 141 deletions(-)

diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index 95f9e8eaac2..7f6a587fade 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -19,25 +19,28 @@ use std::iter::repeat;
 use syntax::ast::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
 use syntax::codemap::Span;
 
-/// A Visitor that walks over an AST and collects Node's into an AST
-/// Map.
+/// A Visitor that walks over the HIR and collects Node's into a HIR map.
 pub struct NodeCollector<'ast> {
     pub krate: &'ast Crate,
     pub map: Vec<MapEntry<'ast>>,
-    pub definitions: Definitions,
     pub parent_node: NodeId,
 }
 
-impl<'ast> NodeCollector<'ast> {
-    pub fn root(krate: &'ast Crate) -> NodeCollector<'ast> {
-        let mut collector = NodeCollector {
-            krate: krate,
-            map: vec![],
-            definitions: Definitions::new(),
-            parent_node: CRATE_NODE_ID,
-        };
-        collector.insert_entry(CRATE_NODE_ID, RootCrate);
+pub struct DefCollector<'ast> {
+    pub krate: &'ast Crate,
+    pub map: &'ast [MapEntry<'ast>],
+    pub definitions: Definitions,
+    pub parent_def: Option<DefIndex>,
+}
 
+impl<'ast> DefCollector<'ast> {
+    pub fn root(krate: &'ast Crate, map: &'ast [MapEntry<'ast>]) -> DefCollector<'ast> {
+        let mut collector = DefCollector {
+            krate: krate,
+            map: map,
+            definitions: Definitions::new(),
+            parent_def: None,
+        };
         let result = collector.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot);
         assert_eq!(result, CRATE_DEF_INDEX);
 
@@ -47,17 +50,16 @@ impl<'ast> NodeCollector<'ast> {
     }
 
     pub fn extend(krate: &'ast Crate,
-                  parent: &'ast InlinedItem,
                   parent_node: NodeId,
                   parent_def_path: DefPath,
                   parent_def_id: DefId,
-                  map: Vec<MapEntry<'ast>>,
+                  map: &'ast [MapEntry<'ast>],
                   definitions: Definitions)
-                  -> NodeCollector<'ast> {
-        let mut collector = NodeCollector {
+                  -> DefCollector<'ast> {
+        let mut collector = DefCollector {
             krate: krate,
             map: map,
-            parent_node: parent_node,
+            parent_def: None,
             definitions: definitions,
         };
 
@@ -67,21 +69,14 @@ impl<'ast> NodeCollector<'ast> {
             def_id: parent_def_id,
         });
 
-        collector.insert_entry(parent_node, RootInlinedParent(parent));
-        collector.create_def(parent_node, DefPathData::InlinedRoot(root_path));
+        let def = collector.create_def(parent_node, DefPathData::InlinedRoot(root_path));
+        collector.parent_def = Some(def);
 
         collector
     }
 
     fn parent_def(&self) -> Option<DefIndex> {
-        let mut parent_node = Some(self.parent_node);
-        while let Some(p) = parent_node {
-            if let Some(q) = self.definitions.opt_def_index(p) {
-                return Some(q);
-            }
-            parent_node = self.map[p as usize].parent_node();
-        }
-        None
+        self.parent_def
     }
 
     fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex {
@@ -97,28 +92,9 @@ impl<'ast> NodeCollector<'ast> {
                               -> DefIndex {
         self.definitions.create_def_with_parent(parent, node_id, data)
     }
-
-    fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) {
-        debug!("ast_map: {:?} => {:?}", id, entry);
-        let len = self.map.len();
-        if id as usize >= len {
-            self.map.extend(repeat(NotPresent).take(id as usize - len + 1));
-        }
-        self.map[id as usize] = entry;
-    }
-
-    fn insert_def(&mut self, id: NodeId, node: Node<'ast>, data: DefPathData) -> DefIndex {
-        self.insert(id, node);
-        self.create_def(id, data)
-    }
-
-    fn insert(&mut self, id: NodeId, node: Node<'ast>) {
-        let entry = MapEntry::from_node(self.parent_node, node);
-        self.insert_entry(id, entry);
-    }
 }
 
-impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
+impl<'ast> Visitor<'ast> for DefCollector<'ast> {
     /// Because we want to track parent items and so forth, enable
     /// deep walking so that we walk nested items in the context of
     /// their outer items.
@@ -146,18 +122,16 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
                 DefPathData::Misc,
         };
 
-        self.insert_def(i.id, NodeItem(i), def_data);
+        let def = self.create_def(i.id, def_data);
 
-        let parent_node = self.parent_node;
-        self.parent_node = i.id;
+        let parent_def = self.parent_def;
+        self.parent_def = Some(def);
 
         match i.node {
-            ItemImpl(..) => {}
             ItemEnum(ref enum_definition, _) => {
                 for v in &enum_definition.variants {
                     let variant_def_index =
-                        self.insert_def(v.node.data.id(),
-                                        NodeVariant(v),
+                        self.create_def(v.node.data.id(),
                                         DefPathData::EnumVariant(v.node.name));
 
                     for field in v.node.data.fields() {
@@ -168,13 +142,10 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
                     }
                 }
             }
-            ItemForeignMod(..) => {
-            }
             ItemStruct(ref struct_def, _) => {
                 // If this is a tuple-like struct, register the constructor.
                 if !struct_def.is_struct() {
-                    self.insert_def(struct_def.id(),
-                                    NodeStructCtor(struct_def),
+                    self.create_def(struct_def.id(),
                                     DefPathData::StructCtor);
                 }
 
@@ -182,6 +153,196 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
                     self.create_def(field.id, DefPathData::Field(field.name));
                 }
             }
+            _ => {}
+        }
+        intravisit::walk_item(self, i);
+        self.parent_def = parent_def;
+    }
+
+    fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
+        let def = self.create_def(foreign_item.id, DefPathData::ValueNs(foreign_item.name));
+
+        let parent_def = self.parent_def;
+        self.parent_def = Some(def);
+        intravisit::walk_foreign_item(self, foreign_item);
+        self.parent_def = parent_def;
+    }
+
+    fn visit_generics(&mut self, generics: &'ast Generics) {
+        for ty_param in generics.ty_params.iter() {
+            self.create_def(ty_param.id,
+                            DefPathData::TypeParam(ty_param.name));
+        }
+
+        intravisit::walk_generics(self, generics);
+    }
+
+    fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
+        let def_data = match ti.node {
+            MethodTraitItem(..) | ConstTraitItem(..) => DefPathData::ValueNs(ti.name),
+            TypeTraitItem(..) => DefPathData::TypeNs(ti.name),
+        };
+
+        let def = self.create_def(ti.id, def_data);
+
+        let parent_def = self.parent_def;
+        self.parent_def = Some(def);
+
+        match ti.node {
+            ConstTraitItem(_, Some(ref expr)) => {
+                self.create_def(expr.id, DefPathData::Initializer);
+            }
+            _ => { }
+        }
+
+        intravisit::walk_trait_item(self, ti);
+
+        self.parent_def = parent_def;
+    }
+
+    fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
+        let def_data = match ii.node {
+            ImplItemKind::Method(..) | ImplItemKind::Const(..) => DefPathData::ValueNs(ii.name),
+            ImplItemKind::Type(..) => DefPathData::TypeNs(ii.name),
+        };
+
+        let def = self.create_def(ii.id, def_data);
+
+        let parent_def = self.parent_def;
+        self.parent_def = Some(def);
+
+        match ii.node {
+            ImplItemKind::Const(_, ref expr) => {
+                self.create_def(expr.id, DefPathData::Initializer);
+            }
+            _ => { }
+        }
+
+        intravisit::walk_impl_item(self, ii);
+
+        self.parent_def = parent_def;
+    }
+
+    fn visit_pat(&mut self, pat: &'ast Pat) {
+        let maybe_binding = match pat.node {
+            PatKind::Ident(_, id, _) => Some(id.node),
+            _ => None
+        };
+
+        let parent_def = self.parent_def;
+        if let Some(id) = maybe_binding {
+            let def = self.create_def(pat.id, DefPathData::Binding(id.name));
+            self.parent_def = Some(def);
+        }
+
+        intravisit::walk_pat(self, pat);
+        self.parent_def = parent_def;
+    }
+
+    fn visit_expr(&mut self, expr: &'ast Expr) {
+        let parent_def = self.parent_def;
+
+        if let ExprClosure(..) = expr.node {
+            let def = self.create_def(expr.id, DefPathData::ClosureExpr);
+            self.parent_def = Some(def);
+        }
+
+        intravisit::walk_expr(self, expr);
+        self.parent_def = parent_def;
+    }
+
+    fn visit_stmt(&mut self, stmt: &'ast Stmt) {
+        intravisit::walk_stmt(self, stmt);
+    }
+
+    fn visit_block(&mut self, block: &'ast Block) {
+        intravisit::walk_block(self, block);
+    }
+
+    fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
+        self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
+    }
+
+    fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
+        self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
+    }
+}
+
+impl<'ast> NodeCollector<'ast> {
+    pub fn root(krate: &'ast Crate) -> NodeCollector<'ast> {
+        let mut collector = NodeCollector {
+            krate: krate,
+            map: vec![],
+            parent_node: CRATE_NODE_ID,
+        };
+        collector.insert_entry(CRATE_NODE_ID, RootCrate);
+
+        collector
+    }
+
+    pub fn extend(krate: &'ast Crate,
+                  parent: &'ast InlinedItem,
+                  parent_node: NodeId,
+                  parent_def_path: DefPath,
+                  parent_def_id: DefId,
+                  map: Vec<MapEntry<'ast>>)
+                  -> NodeCollector<'ast> {
+        let mut collector = NodeCollector {
+            krate: krate,
+            map: map,
+            parent_node: parent_node,
+        };
+
+        assert_eq!(parent_def_path.krate, parent_def_id.krate);
+        collector.insert_entry(parent_node, RootInlinedParent(parent));
+
+        collector
+    }
+
+    fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) {
+        debug!("ast_map: {:?} => {:?}", id, entry);
+        let len = self.map.len();
+        if id as usize >= len {
+            self.map.extend(repeat(NotPresent).take(id as usize - len + 1));
+        }
+        self.map[id as usize] = entry;
+    }
+
+    fn insert(&mut self, id: NodeId, node: Node<'ast>) {
+        let entry = MapEntry::from_node(self.parent_node, node);
+        self.insert_entry(id, entry);
+    }
+}
+
+impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
+    /// Because we want to track parent items and so forth, enable
+    /// deep walking so that we walk nested items in the context of
+    /// their outer items.
+    fn visit_nested_item(&mut self, item: ItemId) {
+        debug!("visit_nested_item: {:?}", item);
+        self.visit_item(self.krate.item(item.id))
+    }
+
+    fn visit_item(&mut self, i: &'ast Item) {
+        debug!("visit_item: {:?}", i);
+
+        self.insert(i.id, NodeItem(i));
+
+        let parent_node = self.parent_node;
+        self.parent_node = i.id;
+
+        match i.node {
+            ItemEnum(ref enum_definition, _) => {
+                for v in &enum_definition.variants {
+                    self.insert(v.node.data.id(), NodeVariant(v));
+                }
+            }
+            ItemStruct(ref struct_def, _) => {
+                // If this is a tuple-like struct, register the constructor.
+                if !struct_def.is_struct() {
+                    self.insert(struct_def.id(), NodeStructCtor(struct_def));
+                }
+            }
             ItemTrait(_, _, ref bounds, _) => {
                 for b in bounds.iter() {
                     if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b {
@@ -206,9 +367,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
-        self.insert_def(foreign_item.id,
-                        NodeForeignItem(foreign_item),
-                        DefPathData::ValueNs(foreign_item.name));
+        self.insert(foreign_item.id, NodeForeignItem(foreign_item));
 
         let parent_node = self.parent_node;
         self.parent_node = foreign_item.id;
@@ -218,72 +377,36 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
 
     fn visit_generics(&mut self, generics: &'ast Generics) {
         for ty_param in generics.ty_params.iter() {
-            self.insert_def(ty_param.id,
-                            NodeTyParam(ty_param),
-                            DefPathData::TypeParam(ty_param.name));
+            self.insert(ty_param.id, NodeTyParam(ty_param));
         }
 
         intravisit::walk_generics(self, generics);
     }
 
     fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
-        let def_data = match ti.node {
-            MethodTraitItem(..) | ConstTraitItem(..) => DefPathData::ValueNs(ti.name),
-            TypeTraitItem(..) => DefPathData::TypeNs(ti.name),
-        };
-
         self.insert(ti.id, NodeTraitItem(ti));
-        self.create_def(ti.id, def_data);
 
         let parent_node = self.parent_node;
         self.parent_node = ti.id;
 
-        match ti.node {
-            ConstTraitItem(_, Some(ref expr)) => {
-                self.create_def(expr.id, DefPathData::Initializer);
-            }
-            _ => { }
-        }
-
         intravisit::walk_trait_item(self, ti);
 
         self.parent_node = parent_node;
     }
 
     fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
-        let def_data = match ii.node {
-            ImplItemKind::Method(..) | ImplItemKind::Const(..) => DefPathData::ValueNs(ii.name),
-            ImplItemKind::Type(..) => DefPathData::TypeNs(ii.name),
-        };
-
-        self.insert_def(ii.id, NodeImplItem(ii), def_data);
+        self.insert(ii.id, NodeImplItem(ii));
 
         let parent_node = self.parent_node;
         self.parent_node = ii.id;
 
-        match ii.node {
-            ImplItemKind::Const(_, ref expr) => {
-                self.create_def(expr.id, DefPathData::Initializer);
-            }
-            _ => { }
-        }
-
         intravisit::walk_impl_item(self, ii);
 
         self.parent_node = parent_node;
     }
 
     fn visit_pat(&mut self, pat: &'ast Pat) {
-        let maybe_binding = match pat.node {
-            PatKind::Ident(_, id, _) => Some(id.node),
-            _ => None
-        };
-
-        if let Some(id) = maybe_binding {
-            self.insert_def(pat.id, NodeLocal(pat), DefPathData::Binding(id.name));
-        } else {
-            self.insert(pat.id, NodePat(pat));
-        }
+        self.insert(pat.id, NodeLocal(pat));
 
         let parent_node = self.parent_node;
         self.parent_node = pat.id;
@@ -294,11 +417,6 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
     fn visit_expr(&mut self, expr: &'ast Expr) {
         self.insert(expr.id, NodeExpr(expr));
 
-        match expr.node {
-            ExprClosure(..) => { self.create_def(expr.id, DefPathData::ClosureExpr); }
-            _ => { }
-        }
-
         let parent_node = self.parent_node;
         self.parent_node = expr.id;
         intravisit::walk_expr(self, expr);
@@ -331,13 +449,4 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
     fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
         self.insert(lifetime.id, NodeLifetime(lifetime));
     }
-
-    fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
-        self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
-        self.visit_lifetime(&def.lifetime);
-    }
-
-    fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
-        self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
-    }
 }
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 7b8ddee0e23..6331f7d3009 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -10,7 +10,7 @@
 
 pub use self::Node::*;
 use self::MapEntry::*;
-use self::collector::NodeCollector;
+use self::collector::{NodeCollector, DefCollector};
 pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,
                             DisambiguatedDefPathData, InlinedRootPath};
 
@@ -784,7 +784,14 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest) -> Map<'ast> {
     let (map, definitions) = {
         let mut collector = NodeCollector::root(&forest.krate);
         intravisit::walk_crate(&mut collector, &forest.krate);
-        (collector.map, collector.definitions)
+
+        let definitions = {
+            let mut def_collector = DefCollector::root(&forest.krate, &collector.map);
+            intravisit::walk_crate(&mut def_collector, &forest.krate);
+            def_collector.definitions
+        };
+
+        (collector.map, definitions)
     };
 
     if log_enabled!(::log::DEBUG) {
@@ -836,19 +843,26 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
     let ii = map.forest.inlined_items.alloc(ii);
 
     let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
-    let mut collector =
-        NodeCollector::extend(
-            map.krate(),
-            ii,
-            ii_parent_id,
-            parent_def_path,
-            parent_def_id,
-            mem::replace(&mut *map.map.borrow_mut(), vec![]),
-            mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new()));
+    let mut collector = NodeCollector::extend(map.krate(),
+                                              ii,
+                                              ii_parent_id,
+                                              parent_def_path.clone(),
+                                              parent_def_id,
+                                              mem::replace(&mut *map.map.borrow_mut(), vec![]));
     ii.visit(&mut collector);
 
+    {
+        let mut def_collector = DefCollector::extend(map.krate(),
+                                                     ii_parent_id,
+                                                     parent_def_path,
+                                                     parent_def_id,
+                                                     &collector.map,
+                                                     mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new()));
+        ii.visit(&mut def_collector);
+        *map.definitions.borrow_mut() = def_collector.definitions;
+    }
+
     *map.map.borrow_mut() = collector.map;
-    *map.definitions.borrow_mut() = collector.definitions;
 
     ii
 }
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 9c444fca9a1..c211fa2925e 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -120,6 +120,27 @@ pub fn compile_input(sess: &Session,
                                 Ok(()));
 
         let expanded_crate = assign_node_ids(sess, expanded_crate);
+        let dep_graph = DepGraph::new(sess.opts.build_dep_graph);
+        
+        // TODO
+        // time(sess.time_passes(),
+        //      "external crate/lib resolution",
+        //      || LocalCrateReader::new(sess, &cstore, &defs, &id).read_crates());
+
+        // TODO
+        panic!();
+
+        // TODO CrateMap result
+        // let resolve::CrateMap {
+        //     def_map,
+        //     freevars,
+        //     export_map,
+        //     trait_map,
+        //     glob_map,
+        // } = time(sess.time_passes(),
+        //          "name resolution",
+        //          || resolve::resolve_crate(sess, &hir_map, control.make_glob_map));
+
         // Lower ast -> hir.
         let lcx = LoweringContext::new(sess, Some(&expanded_crate));
         let dep_graph = DepGraph::new(sess.opts.build_dep_graph());
@@ -175,7 +196,6 @@ pub fn compile_input(sess: &Session,
                                     hir_map,
                                     &arenas,
                                     &id,
-                                    control.make_glob_map,
                                     |tcx, mir_map, analysis, result| {
             {
                 // Eventually, we will want to track plugins.
@@ -743,7 +763,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                                                hir_map: hir_map::Map<'tcx>,
                                                arenas: &'tcx ty::CtxtArenas<'tcx>,
                                                name: &str,
-                                               make_glob_map: resolve::MakeGlobMap,
                                                f: F)
                                                -> Result<R, usize>
     where F: FnOnce(&TyCtxt<'tcx>, Option<MirMap<'tcx>>, ty::CrateAnalysis, CompileResult) -> R
@@ -762,20 +781,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
     let time_passes = sess.time_passes();
 
-    time(time_passes,
-         "external crate/lib resolution",
-         || LocalCrateReader::new(sess, cstore, &hir_map, name).read_crates());
-
-    let resolve::CrateMap {
-        def_map,
-        freevars,
-        export_map,
-        trait_map,
-        glob_map,
-    } = time(time_passes,
-             "name resolution",
-             || resolve::resolve_crate(sess, &hir_map, make_glob_map));
-
     let lang_items = time(time_passes, "language item collection", || {
         sess.track_errors(|| {
             middle::lang_items::collect_language_items(&sess, &hir_map)

From d6bcc04c521bcdf82b7727ec35e3f6ce0cbb5b0f Mon Sep 17 00:00:00 2001
From: Nick Cameron <ncameron@mozilla.com>
Date: Thu, 14 Apr 2016 12:14:03 +1200
Subject: [PATCH 3/9] Move DefCollector to its own module.

---
 src/librustc/hir/map/collector.rs     | 248 +------------------------
 src/librustc/hir/map/def_collector.rs | 258 ++++++++++++++++++++++++++
 src/librustc/hir/map/mod.rs           |   7 +-
 src/librustc_driver/driver.rs         |   2 +-
 4 files changed, 267 insertions(+), 248 deletions(-)
 create mode 100644 src/librustc/hir/map/def_collector.rs

diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index 7f6a587fade..d7fccf03aec 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -1,4 +1,4 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2015-2016 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -13,10 +13,10 @@ use super::MapEntry::*;
 
 use hir::*;
 use hir::intravisit::Visitor;
-use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
+use hir::def_id::DefId;
 use middle::cstore::InlinedItem;
 use std::iter::repeat;
-use syntax::ast::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
+use syntax::ast::{NodeId, CRATE_NODE_ID};
 use syntax::codemap::Span;
 
 /// A Visitor that walks over the HIR and collects Node's into a HIR map.
@@ -26,248 +26,6 @@ pub struct NodeCollector<'ast> {
     pub parent_node: NodeId,
 }
 
-pub struct DefCollector<'ast> {
-    pub krate: &'ast Crate,
-    pub map: &'ast [MapEntry<'ast>],
-    pub definitions: Definitions,
-    pub parent_def: Option<DefIndex>,
-}
-
-impl<'ast> DefCollector<'ast> {
-    pub fn root(krate: &'ast Crate, map: &'ast [MapEntry<'ast>]) -> DefCollector<'ast> {
-        let mut collector = DefCollector {
-            krate: krate,
-            map: map,
-            definitions: Definitions::new(),
-            parent_def: None,
-        };
-        let result = collector.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot);
-        assert_eq!(result, CRATE_DEF_INDEX);
-
-        collector.create_def_with_parent(Some(CRATE_DEF_INDEX), DUMMY_NODE_ID, DefPathData::Misc);
-
-        collector
-    }
-
-    pub fn extend(krate: &'ast Crate,
-                  parent_node: NodeId,
-                  parent_def_path: DefPath,
-                  parent_def_id: DefId,
-                  map: &'ast [MapEntry<'ast>],
-                  definitions: Definitions)
-                  -> DefCollector<'ast> {
-        let mut collector = DefCollector {
-            krate: krate,
-            map: map,
-            parent_def: None,
-            definitions: definitions,
-        };
-
-        assert_eq!(parent_def_path.krate, parent_def_id.krate);
-        let root_path = Box::new(InlinedRootPath {
-            data: parent_def_path.data,
-            def_id: parent_def_id,
-        });
-
-        let def = collector.create_def(parent_node, DefPathData::InlinedRoot(root_path));
-        collector.parent_def = Some(def);
-
-        collector
-    }
-
-    fn parent_def(&self) -> Option<DefIndex> {
-        self.parent_def
-    }
-
-    fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex {
-        let parent_def = self.parent_def();
-        debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
-        self.definitions.create_def_with_parent(parent_def, node_id, data)
-    }
-
-    fn create_def_with_parent(&mut self,
-                              parent: Option<DefIndex>,
-                              node_id: NodeId,
-                              data: DefPathData)
-                              -> DefIndex {
-        self.definitions.create_def_with_parent(parent, node_id, data)
-    }
-}
-
-impl<'ast> Visitor<'ast> for DefCollector<'ast> {
-    /// Because we want to track parent items and so forth, enable
-    /// deep walking so that we walk nested items in the context of
-    /// their outer items.
-    fn visit_nested_item(&mut self, item: ItemId) {
-        debug!("visit_nested_item: {:?}", item);
-        self.visit_item(self.krate.item(item.id))
-    }
-
-    fn visit_item(&mut self, i: &'ast Item) {
-        debug!("visit_item: {:?}", i);
-
-        // Pick the def data. This need not be unique, but the more
-        // information we encapsulate into
-        let def_data = match i.node {
-            ItemDefaultImpl(..) | ItemImpl(..) =>
-                DefPathData::Impl,
-            ItemEnum(..) | ItemStruct(..) | ItemTrait(..) |
-            ItemExternCrate(..) | ItemForeignMod(..) | ItemTy(..) =>
-                DefPathData::TypeNs(i.name),
-            ItemMod(..) =>
-                DefPathData::Module(i.name),
-            ItemStatic(..) | ItemConst(..) | ItemFn(..) =>
-                DefPathData::ValueNs(i.name),
-            ItemUse(..) =>
-                DefPathData::Misc,
-        };
-
-        let def = self.create_def(i.id, def_data);
-
-        let parent_def = self.parent_def;
-        self.parent_def = Some(def);
-
-        match i.node {
-            ItemEnum(ref enum_definition, _) => {
-                for v in &enum_definition.variants {
-                    let variant_def_index =
-                        self.create_def(v.node.data.id(),
-                                        DefPathData::EnumVariant(v.node.name));
-
-                    for field in v.node.data.fields() {
-                        self.create_def_with_parent(
-                            Some(variant_def_index),
-                            field.id,
-                            DefPathData::Field(field.name));
-                    }
-                }
-            }
-            ItemStruct(ref struct_def, _) => {
-                // If this is a tuple-like struct, register the constructor.
-                if !struct_def.is_struct() {
-                    self.create_def(struct_def.id(),
-                                    DefPathData::StructCtor);
-                }
-
-                for field in struct_def.fields() {
-                    self.create_def(field.id, DefPathData::Field(field.name));
-                }
-            }
-            _ => {}
-        }
-        intravisit::walk_item(self, i);
-        self.parent_def = parent_def;
-    }
-
-    fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
-        let def = self.create_def(foreign_item.id, DefPathData::ValueNs(foreign_item.name));
-
-        let parent_def = self.parent_def;
-        self.parent_def = Some(def);
-        intravisit::walk_foreign_item(self, foreign_item);
-        self.parent_def = parent_def;
-    }
-
-    fn visit_generics(&mut self, generics: &'ast Generics) {
-        for ty_param in generics.ty_params.iter() {
-            self.create_def(ty_param.id,
-                            DefPathData::TypeParam(ty_param.name));
-        }
-
-        intravisit::walk_generics(self, generics);
-    }
-
-    fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
-        let def_data = match ti.node {
-            MethodTraitItem(..) | ConstTraitItem(..) => DefPathData::ValueNs(ti.name),
-            TypeTraitItem(..) => DefPathData::TypeNs(ti.name),
-        };
-
-        let def = self.create_def(ti.id, def_data);
-
-        let parent_def = self.parent_def;
-        self.parent_def = Some(def);
-
-        match ti.node {
-            ConstTraitItem(_, Some(ref expr)) => {
-                self.create_def(expr.id, DefPathData::Initializer);
-            }
-            _ => { }
-        }
-
-        intravisit::walk_trait_item(self, ti);
-
-        self.parent_def = parent_def;
-    }
-
-    fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
-        let def_data = match ii.node {
-            ImplItemKind::Method(..) | ImplItemKind::Const(..) => DefPathData::ValueNs(ii.name),
-            ImplItemKind::Type(..) => DefPathData::TypeNs(ii.name),
-        };
-
-        let def = self.create_def(ii.id, def_data);
-
-        let parent_def = self.parent_def;
-        self.parent_def = Some(def);
-
-        match ii.node {
-            ImplItemKind::Const(_, ref expr) => {
-                self.create_def(expr.id, DefPathData::Initializer);
-            }
-            _ => { }
-        }
-
-        intravisit::walk_impl_item(self, ii);
-
-        self.parent_def = parent_def;
-    }
-
-    fn visit_pat(&mut self, pat: &'ast Pat) {
-        let maybe_binding = match pat.node {
-            PatKind::Ident(_, id, _) => Some(id.node),
-            _ => None
-        };
-
-        let parent_def = self.parent_def;
-        if let Some(id) = maybe_binding {
-            let def = self.create_def(pat.id, DefPathData::Binding(id.name));
-            self.parent_def = Some(def);
-        }
-
-        intravisit::walk_pat(self, pat);
-        self.parent_def = parent_def;
-    }
-
-    fn visit_expr(&mut self, expr: &'ast Expr) {
-        let parent_def = self.parent_def;
-
-        if let ExprClosure(..) = expr.node {
-            let def = self.create_def(expr.id, DefPathData::ClosureExpr);
-            self.parent_def = Some(def);
-        }
-
-        intravisit::walk_expr(self, expr);
-        self.parent_def = parent_def;
-    }
-
-    fn visit_stmt(&mut self, stmt: &'ast Stmt) {
-        intravisit::walk_stmt(self, stmt);
-    }
-
-    fn visit_block(&mut self, block: &'ast Block) {
-        intravisit::walk_block(self, block);
-    }
-
-    fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
-        self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
-    }
-
-    fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
-        self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
-    }
-}
-
 impl<'ast> NodeCollector<'ast> {
     pub fn root(krate: &'ast Crate) -> NodeCollector<'ast> {
         let mut collector = NodeCollector {
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
new file mode 100644
index 00000000000..0e64a2d676e
--- /dev/null
+++ b/src/librustc/hir/map/def_collector.rs
@@ -0,0 +1,258 @@
+// 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.
+
+use super::*;
+
+use hir::*;
+use hir::intravisit::Visitor;
+use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
+use syntax::ast::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
+
+/// Creates def ids for nodes in the HIR.
+pub struct DefCollector<'ast> {
+    pub krate: &'ast Crate,
+    pub map: &'ast [MapEntry<'ast>],
+    pub definitions: Definitions,
+    pub parent_def: Option<DefIndex>,
+}
+
+impl<'ast> DefCollector<'ast> {
+    pub fn root(krate: &'ast Crate, map: &'ast [MapEntry<'ast>]) -> DefCollector<'ast> {
+        let mut collector = DefCollector {
+            krate: krate,
+            map: map,
+            definitions: Definitions::new(),
+            parent_def: None,
+        };
+        let result = collector.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot);
+        assert_eq!(result, CRATE_DEF_INDEX);
+
+        collector.create_def_with_parent(Some(CRATE_DEF_INDEX), DUMMY_NODE_ID, DefPathData::Misc);
+
+        collector
+    }
+
+    pub fn extend(krate: &'ast Crate,
+                  parent_node: NodeId,
+                  parent_def_path: DefPath,
+                  parent_def_id: DefId,
+                  map: &'ast [MapEntry<'ast>],
+                  definitions: Definitions)
+                  -> DefCollector<'ast> {
+        let mut collector = DefCollector {
+            krate: krate,
+            map: map,
+            parent_def: None,
+            definitions: definitions,
+        };
+
+        assert_eq!(parent_def_path.krate, parent_def_id.krate);
+        let root_path = Box::new(InlinedRootPath {
+            data: parent_def_path.data,
+            def_id: parent_def_id,
+        });
+
+        let def = collector.create_def(parent_node, DefPathData::InlinedRoot(root_path));
+        collector.parent_def = Some(def);
+
+        collector
+    }
+
+    fn parent_def(&self) -> Option<DefIndex> {
+        self.parent_def
+    }
+
+    fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex {
+        let parent_def = self.parent_def();
+        debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
+        self.definitions.create_def_with_parent(parent_def, node_id, data)
+    }
+
+    fn create_def_with_parent(&mut self,
+                              parent: Option<DefIndex>,
+                              node_id: NodeId,
+                              data: DefPathData)
+                              -> DefIndex {
+        self.definitions.create_def_with_parent(parent, node_id, data)
+    }
+}
+
+impl<'ast> Visitor<'ast> for DefCollector<'ast> {
+    /// Because we want to track parent items and so forth, enable
+    /// deep walking so that we walk nested items in the context of
+    /// their outer items.
+    fn visit_nested_item(&mut self, item: ItemId) {
+        debug!("visit_nested_item: {:?}", item);
+        self.visit_item(self.krate.item(item.id))
+    }
+
+    fn visit_item(&mut self, i: &'ast Item) {
+        debug!("visit_item: {:?}", i);
+
+        // Pick the def data. This need not be unique, but the more
+        // information we encapsulate into
+        let def_data = match i.node {
+            ItemDefaultImpl(..) | ItemImpl(..) =>
+                DefPathData::Impl,
+            ItemEnum(..) | ItemStruct(..) | ItemTrait(..) |
+            ItemExternCrate(..) | ItemMod(..) | ItemForeignMod(..) |
+            ItemTy(..) =>
+                DefPathData::TypeNs(i.name),
+            ItemStatic(..) | ItemConst(..) | ItemFn(..) =>
+                DefPathData::ValueNs(i.name),
+            ItemUse(..) =>
+                DefPathData::Misc,
+        };
+
+        let def = self.create_def(i.id, def_data);
+
+        let parent_def = self.parent_def;
+        self.parent_def = Some(def);
+
+        match i.node {
+            ItemEnum(ref enum_definition, _) => {
+                for v in &enum_definition.variants {
+                    let variant_def_index =
+                        self.create_def(v.node.data.id(),
+                                        DefPathData::EnumVariant(v.node.name));
+
+                    for field in v.node.data.fields() {
+                        self.create_def_with_parent(
+                            Some(variant_def_index),
+                            field.id,
+                            DefPathData::Field(field.name));
+                    }
+                }
+            }
+            ItemStruct(ref struct_def, _) => {
+                // If this is a tuple-like struct, register the constructor.
+                if !struct_def.is_struct() {
+                    self.create_def(struct_def.id(),
+                                    DefPathData::StructCtor);
+                }
+
+                for field in struct_def.fields() {
+                    self.create_def(field.id, DefPathData::Field(field.name));
+                }
+            }
+            _ => {}
+        }
+        intravisit::walk_item(self, i);
+        self.parent_def = parent_def;
+    }
+
+    fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
+        let def = self.create_def(foreign_item.id, DefPathData::ValueNs(foreign_item.name));
+
+        let parent_def = self.parent_def;
+        self.parent_def = Some(def);
+        intravisit::walk_foreign_item(self, foreign_item);
+        self.parent_def = parent_def;
+    }
+
+    fn visit_generics(&mut self, generics: &'ast Generics) {
+        for ty_param in generics.ty_params.iter() {
+            self.create_def(ty_param.id,
+                            DefPathData::TypeParam(ty_param.name));
+        }
+
+        intravisit::walk_generics(self, generics);
+    }
+
+    fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
+        let def_data = match ti.node {
+            MethodTraitItem(..) | ConstTraitItem(..) => DefPathData::ValueNs(ti.name),
+            TypeTraitItem(..) => DefPathData::TypeNs(ti.name),
+        };
+
+        let def = self.create_def(ti.id, def_data);
+
+        let parent_def = self.parent_def;
+        self.parent_def = Some(def);
+
+        match ti.node {
+            ConstTraitItem(_, Some(ref expr)) => {
+                self.create_def(expr.id, DefPathData::Initializer);
+            }
+            _ => { }
+        }
+
+        intravisit::walk_trait_item(self, ti);
+
+        self.parent_def = parent_def;
+    }
+
+    fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
+        let def_data = match ii.node {
+            ImplItemKind::Method(..) | ImplItemKind::Const(..) => DefPathData::ValueNs(ii.name),
+            ImplItemKind::Type(..) => DefPathData::TypeNs(ii.name),
+        };
+
+        let def = self.create_def(ii.id, def_data);
+
+        let parent_def = self.parent_def;
+        self.parent_def = Some(def);
+
+        match ii.node {
+            ImplItemKind::Const(_, ref expr) => {
+                self.create_def(expr.id, DefPathData::Initializer);
+            }
+            _ => { }
+        }
+
+        intravisit::walk_impl_item(self, ii);
+
+        self.parent_def = parent_def;
+    }
+
+    fn visit_pat(&mut self, pat: &'ast Pat) {
+        let maybe_binding = match pat.node {
+            PatKind::Ident(_, id, _) => Some(id.node),
+            _ => None
+        };
+
+        let parent_def = self.parent_def;
+        if let Some(id) = maybe_binding {
+            let def = self.create_def(pat.id, DefPathData::Binding(id.name));
+            self.parent_def = Some(def);
+        }
+
+        intravisit::walk_pat(self, pat);
+        self.parent_def = parent_def;
+    }
+
+    fn visit_expr(&mut self, expr: &'ast Expr) {
+        let parent_def = self.parent_def;
+
+        if let ExprClosure(..) = expr.node {
+            let def = self.create_def(expr.id, DefPathData::ClosureExpr);
+            self.parent_def = Some(def);
+        }
+
+        intravisit::walk_expr(self, expr);
+        self.parent_def = parent_def;
+    }
+
+    fn visit_stmt(&mut self, stmt: &'ast Stmt) {
+        intravisit::walk_stmt(self, stmt);
+    }
+
+    fn visit_block(&mut self, block: &'ast Block) {
+        intravisit::walk_block(self, block);
+    }
+
+    fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
+        self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
+    }
+
+    fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
+        self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
+    }
+}
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 6331f7d3009..d0ec83b7eb3 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -10,7 +10,8 @@
 
 pub use self::Node::*;
 use self::MapEntry::*;
-use self::collector::{NodeCollector, DefCollector};
+use self::collector::NodeCollector;
+use self::def_collector::DefCollector;
 pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,
                             DisambiguatedDefPathData, InlinedRootPath};
 
@@ -36,6 +37,7 @@ use std::mem;
 
 pub mod blocks;
 mod collector;
+mod def_collector;
 pub mod definitions;
 
 #[derive(Copy, Clone, Debug)]
@@ -852,12 +854,13 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
     ii.visit(&mut collector);
 
     {
+        let defs = mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new());
         let mut def_collector = DefCollector::extend(map.krate(),
                                                      ii_parent_id,
                                                      parent_def_path,
                                                      parent_def_id,
                                                      &collector.map,
-                                                     mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new()));
+                                                     defs);
         ii.visit(&mut def_collector);
         *map.definitions.borrow_mut() = def_collector.definitions;
     }
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index c211fa2925e..488e7ae56ef 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -121,7 +121,7 @@ pub fn compile_input(sess: &Session,
 
         let expanded_crate = assign_node_ids(sess, expanded_crate);
         let dep_graph = DepGraph::new(sess.opts.build_dep_graph);
-        
+
         // TODO
         // time(sess.time_passes(),
         //      "external crate/lib resolution",

From 6af7acab1c6976933c90b07a58450567227b4719 Mon Sep 17 00:00:00 2001
From: Nick Cameron <ncameron@mozilla.com>
Date: Thu, 14 Apr 2016 12:39:18 +1200
Subject: [PATCH 4/9] Separate def collection and hir map making even further

---
 src/librustc/hir/map/def_collector.rs |  6 +---
 src/librustc/hir/map/mod.rs           | 47 ++++++++++++---------------
 src/librustc_driver/driver.rs         | 20 ++++++------
 src/librustc_driver/pretty.rs         |  3 +-
 4 files changed, 33 insertions(+), 43 deletions(-)

diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index 0e64a2d676e..974791f62bb 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -18,16 +18,14 @@ use syntax::ast::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
 /// Creates def ids for nodes in the HIR.
 pub struct DefCollector<'ast> {
     pub krate: &'ast Crate,
-    pub map: &'ast [MapEntry<'ast>],
     pub definitions: Definitions,
     pub parent_def: Option<DefIndex>,
 }
 
 impl<'ast> DefCollector<'ast> {
-    pub fn root(krate: &'ast Crate, map: &'ast [MapEntry<'ast>]) -> DefCollector<'ast> {
+    pub fn root(krate: &'ast Crate) -> DefCollector<'ast> {
         let mut collector = DefCollector {
             krate: krate,
-            map: map,
             definitions: Definitions::new(),
             parent_def: None,
         };
@@ -43,12 +41,10 @@ impl<'ast> DefCollector<'ast> {
                   parent_node: NodeId,
                   parent_def_path: DefPath,
                   parent_def_id: DefId,
-                  map: &'ast [MapEntry<'ast>],
                   definitions: Definitions)
                   -> DefCollector<'ast> {
         let mut collector = DefCollector {
             krate: krate,
-            map: map,
             parent_def: None,
             definitions: definitions,
         };
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index d0ec83b7eb3..70071c224f8 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -782,19 +782,16 @@ impl<F: FoldOps> Folder for IdAndSpanUpdater<F> {
     }
 }
 
-pub fn map_crate<'ast>(forest: &'ast mut Forest) -> Map<'ast> {
-    let (map, definitions) = {
-        let mut collector = NodeCollector::root(&forest.krate);
-        intravisit::walk_crate(&mut collector, &forest.krate);
+pub fn collect_definitions<'ast>(forest: &'ast mut Forest) -> Definitions {
+    let mut def_collector = DefCollector::root(&forest.krate);
+    intravisit::walk_crate(&mut def_collector, &forest.krate);
+    def_collector.definitions    
+}
 
-        let definitions = {
-            let mut def_collector = DefCollector::root(&forest.krate, &collector.map);
-            intravisit::walk_crate(&mut def_collector, &forest.krate);
-            def_collector.definitions
-        };
-
-        (collector.map, definitions)
-    };
+pub fn map_crate<'ast>(forest: &'ast mut Forest, definitions: Definitions) -> Map<'ast> {
+    let mut collector = NodeCollector::root(&forest.krate);
+    intravisit::walk_crate(&mut collector, &forest.krate);
+    let map = collector.map;
 
     if log_enabled!(::log::DEBUG) {
         // This only makes sense for ordered stores; note the
@@ -843,28 +840,24 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
     };
 
     let ii = map.forest.inlined_items.alloc(ii);
-
     let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
+
+    let defs = mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new());
+    let mut def_collector = DefCollector::extend(map.krate(),
+                                                 ii_parent_id,
+                                                 parent_def_path.clone(),
+                                                 parent_def_id,
+                                                 defs);
+    ii.visit(&mut def_collector);
+    *map.definitions.borrow_mut() = def_collector.definitions;
+
     let mut collector = NodeCollector::extend(map.krate(),
                                               ii,
                                               ii_parent_id,
-                                              parent_def_path.clone(),
+                                              parent_def_path,
                                               parent_def_id,
                                               mem::replace(&mut *map.map.borrow_mut(), vec![]));
     ii.visit(&mut collector);
-
-    {
-        let defs = mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new());
-        let mut def_collector = DefCollector::extend(map.krate(),
-                                                     ii_parent_id,
-                                                     parent_def_path,
-                                                     parent_def_id,
-                                                     &collector.map,
-                                                     defs);
-        ii.visit(&mut def_collector);
-        *map.definitions.borrow_mut() = def_collector.definitions;
-    }
-
     *map.map.borrow_mut() = collector.map;
 
     ii
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 488e7ae56ef..d63cf875632 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -156,7 +156,16 @@ pub fn compile_input(sess: &Session,
         }
 
         let arenas = ty::CtxtArenas::new();
-        let hir_map = make_map(sess, &mut hir_forest);
+        // Collect defintions for def ids.
+        let defs = time(sess.time_passes(),
+                        "collecting defs",
+                        move || hir_map::collect_defs(hir_forest));
+
+        // Construct the HIR map
+        let hir_map = time(sess.time_passes(),
+                           "indexing hir",
+                           move || hir_map::map_crate(hir_forest, defs));
+
 
         write_out_deps(sess, &outputs, &id);
 
@@ -746,15 +755,6 @@ pub fn assign_node_ids(sess: &Session, krate: ast::Crate) -> ast::Crate {
     krate
 }
 
-pub fn make_map<'ast>(sess: &Session,
-                      forest: &'ast mut hir_map::Forest)
-                      -> hir_map::Map<'ast> {
-    // Construct the HIR map
-    time(sess.time_passes(),
-         "indexing hir",
-         move || hir_map::map_crate(forest))
-}
-
 /// Run the resolution, typechecking, region checking and other
 /// miscellaneous analysis passes on the crate. Return various
 /// structures carrying the results of the analysis.
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index cde5ba19859..228cb8d75af 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -738,7 +738,8 @@ pub fn pretty_print_input(sess: Session,
     let _ignore = dep_graph.in_ignore();
     let ast_map = if compute_ast_map {
         hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate), dep_graph.clone());
-        let map = driver::make_map(&sess, &mut hir_forest);
+        let defs = hir_map::collect_defs(hir_forest);
+        let map = hir_map::map_crate(hir_forest, defs);
         Some(map)
     } else {
         None

From 84c3f898f93e294f2e50ceef271bd781b1ff6b9a Mon Sep 17 00:00:00 2001
From: Nick Cameron <ncameron@mozilla.com>
Date: Thu, 14 Apr 2016 14:51:21 +1200
Subject: [PATCH 5/9] def_collector and crate reader operate on AST instead of
 HIR

And move extern crate reading earlier in the driver
---
 src/librustc/hir/map/def_collector.rs | 92 +++++++++++++--------------
 src/librustc/hir/map/mod.rs           | 28 ++++----
 src/librustc_driver/driver.rs         | 52 +++++++--------
 src/librustc_driver/pretty.rs         | 10 +--
 src/librustc_metadata/creader.rs      | 80 ++++++++---------------
 5 files changed, 112 insertions(+), 150 deletions(-)

diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index 974791f62bb..a259c5a0f31 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -10,10 +10,10 @@
 
 use super::*;
 
-use hir::*;
-use hir::intravisit::Visitor;
 use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
-use syntax::ast::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
+
+use syntax::ast::*;
+use syntax::visit;
 
 /// Creates def ids for nodes in the HIR.
 pub struct DefCollector<'ast> {
@@ -80,31 +80,23 @@ impl<'ast> DefCollector<'ast> {
     }
 }
 
-impl<'ast> Visitor<'ast> for DefCollector<'ast> {
-    /// Because we want to track parent items and so forth, enable
-    /// deep walking so that we walk nested items in the context of
-    /// their outer items.
-    fn visit_nested_item(&mut self, item: ItemId) {
-        debug!("visit_nested_item: {:?}", item);
-        self.visit_item(self.krate.item(item.id))
-    }
-
+impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
     fn visit_item(&mut self, i: &'ast Item) {
         debug!("visit_item: {:?}", i);
 
         // Pick the def data. This need not be unique, but the more
         // information we encapsulate into
         let def_data = match i.node {
-            ItemDefaultImpl(..) | ItemImpl(..) =>
+            ItemKind::DefaultImpl(..) | ItemKind::Impl(..) =>
                 DefPathData::Impl,
-            ItemEnum(..) | ItemStruct(..) | ItemTrait(..) |
-            ItemExternCrate(..) | ItemMod(..) | ItemForeignMod(..) |
-            ItemTy(..) =>
-                DefPathData::TypeNs(i.name),
-            ItemStatic(..) | ItemConst(..) | ItemFn(..) =>
-                DefPathData::ValueNs(i.name),
-            ItemUse(..) =>
-                DefPathData::Misc,
+            ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Trait(..) |
+            ItemKind::ExternCrate(..) | ItemKind::Mod(..) | ItemKind::ForeignMod(..) |
+            ItemKind::Ty(..) =>
+                DefPathData::TypeNs(i.ident.name),
+            ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
+                DefPathData::ValueNs(i.ident.name),
+            ItemKind::Mac(..) => DefPathData::MacroDef(i.ident.name),
+            ItemKind::Use(..) => DefPathData::Misc,
         };
 
         let def = self.create_def(i.id, def_data);
@@ -113,21 +105,22 @@ impl<'ast> Visitor<'ast> for DefCollector<'ast> {
         self.parent_def = Some(def);
 
         match i.node {
-            ItemEnum(ref enum_definition, _) => {
+            ItemKind::Enum(ref enum_definition, _) => {
                 for v in &enum_definition.variants {
                     let variant_def_index =
                         self.create_def(v.node.data.id(),
-                                        DefPathData::EnumVariant(v.node.name));
+                                        DefPathData::EnumVariant(v.node.name.name));
 
                     for field in v.node.data.fields() {
-                        self.create_def_with_parent(
-                            Some(variant_def_index),
-                            field.id,
-                            DefPathData::Field(field.name));
+                        if let Some(ident) = field.ident {
+                            self.create_def_with_parent(Some(variant_def_index),
+                                                        field.id,
+                                                        DefPathData::Field(ident.name));
+                        }
                     }
                 }
             }
-            ItemStruct(ref struct_def, _) => {
+            ItemKind::Struct(ref struct_def, _) => {
                 // If this is a tuple-like struct, register the constructor.
                 if !struct_def.is_struct() {
                     self.create_def(struct_def.id(),
@@ -135,37 +128,40 @@ impl<'ast> Visitor<'ast> for DefCollector<'ast> {
                 }
 
                 for field in struct_def.fields() {
-                    self.create_def(field.id, DefPathData::Field(field.name));
+                    if let Some(ident) = field.ident {
+                        self.create_def(field.id, DefPathData::Field(ident.name));
+                    }
                 }
             }
             _ => {}
         }
-        intravisit::walk_item(self, i);
+        visit::walk_item(self, i);
         self.parent_def = parent_def;
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
-        let def = self.create_def(foreign_item.id, DefPathData::ValueNs(foreign_item.name));
+        let def = self.create_def(foreign_item.id, DefPathData::ValueNs(foreign_item.ident.name));
 
         let parent_def = self.parent_def;
         self.parent_def = Some(def);
-        intravisit::walk_foreign_item(self, foreign_item);
+        visit::walk_foreign_item(self, foreign_item);
         self.parent_def = parent_def;
     }
 
     fn visit_generics(&mut self, generics: &'ast Generics) {
         for ty_param in generics.ty_params.iter() {
             self.create_def(ty_param.id,
-                            DefPathData::TypeParam(ty_param.name));
+                            DefPathData::TypeParam(ty_param.ident.name));
         }
 
-        intravisit::walk_generics(self, generics);
+        visit::walk_generics(self, generics);
     }
 
     fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
         let def_data = match ti.node {
-            MethodTraitItem(..) | ConstTraitItem(..) => DefPathData::ValueNs(ti.name),
-            TypeTraitItem(..) => DefPathData::TypeNs(ti.name),
+            TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
+                DefPathData::ValueNs(ti.ident.name),
+            TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name),
         };
 
         let def = self.create_def(ti.id, def_data);
@@ -174,21 +170,23 @@ impl<'ast> Visitor<'ast> for DefCollector<'ast> {
         self.parent_def = Some(def);
 
         match ti.node {
-            ConstTraitItem(_, Some(ref expr)) => {
+            TraitItemKind::Const(_, Some(ref expr)) => {
                 self.create_def(expr.id, DefPathData::Initializer);
             }
             _ => { }
         }
 
-        intravisit::walk_trait_item(self, ti);
+        visit::walk_trait_item(self, ti);
 
         self.parent_def = parent_def;
     }
 
     fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
         let def_data = match ii.node {
-            ImplItemKind::Method(..) | ImplItemKind::Const(..) => DefPathData::ValueNs(ii.name),
-            ImplItemKind::Type(..) => DefPathData::TypeNs(ii.name),
+            ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
+                DefPathData::ValueNs(ii.ident.name),
+            ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name),
+            ImplItemKind::Macro(..) => DefPathData::MacroDef(ii.ident.name),
         };
 
         let def = self.create_def(ii.id, def_data);
@@ -203,7 +201,7 @@ impl<'ast> Visitor<'ast> for DefCollector<'ast> {
             _ => { }
         }
 
-        intravisit::walk_impl_item(self, ii);
+        visit::walk_impl_item(self, ii);
 
         self.parent_def = parent_def;
     }
@@ -220,28 +218,28 @@ impl<'ast> Visitor<'ast> for DefCollector<'ast> {
             self.parent_def = Some(def);
         }
 
-        intravisit::walk_pat(self, pat);
+        visit::walk_pat(self, pat);
         self.parent_def = parent_def;
     }
 
     fn visit_expr(&mut self, expr: &'ast Expr) {
         let parent_def = self.parent_def;
 
-        if let ExprClosure(..) = expr.node {
+        if let ExprKind::Closure(..) = expr.node {
             let def = self.create_def(expr.id, DefPathData::ClosureExpr);
             self.parent_def = Some(def);
         }
 
-        intravisit::walk_expr(self, expr);
+        visit::walk_expr(self, expr);
         self.parent_def = parent_def;
     }
 
     fn visit_stmt(&mut self, stmt: &'ast Stmt) {
-        intravisit::walk_stmt(self, stmt);
+        visit::walk_stmt(self, stmt);
     }
 
     fn visit_block(&mut self, block: &'ast Block) {
-        intravisit::walk_block(self, block);
+        visit::walk_block(self, block);
     }
 
     fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
@@ -249,6 +247,6 @@ impl<'ast> Visitor<'ast> for DefCollector<'ast> {
     }
 
     fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
-        self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
+        self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.ident.name));
     }
 }
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 70071c224f8..b1954255278 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -22,9 +22,10 @@ use middle::cstore::InlinedItem as II;
 use hir::def_id::{CRATE_DEF_INDEX, DefId};
 
 use syntax::abi::Abi;
-use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID};
+use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, };
 use syntax::attr::ThinAttributesExt;
 use syntax::codemap::{Span, Spanned};
+use syntax::visit;
 
 use hir::*;
 use hir::fold::Folder;
@@ -782,10 +783,10 @@ impl<F: FoldOps> Folder for IdAndSpanUpdater<F> {
     }
 }
 
-pub fn collect_definitions<'ast>(forest: &'ast mut Forest) -> Definitions {
-    let mut def_collector = DefCollector::root(&forest.krate);
-    intravisit::walk_crate(&mut def_collector, &forest.krate);
-    def_collector.definitions    
+pub fn collect_definitions<'ast>(krate: &'ast ast::Crate) -> Definitions {
+    let mut def_collector = DefCollector::root(krate);
+    visit::walk_crate(&mut def_collector, krate);
+    def_collector.definitions
 }
 
 pub fn map_crate<'ast>(forest: &'ast mut Forest, definitions: Definitions) -> Map<'ast> {
@@ -842,14 +843,15 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
     let ii = map.forest.inlined_items.alloc(ii);
     let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
 
-    let defs = mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new());
-    let mut def_collector = DefCollector::extend(map.krate(),
-                                                 ii_parent_id,
-                                                 parent_def_path.clone(),
-                                                 parent_def_id,
-                                                 defs);
-    ii.visit(&mut def_collector);
-    *map.definitions.borrow_mut() = def_collector.definitions;
+    // TODO need to save defs in metadata :-(
+    // let defs = mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new());
+    // let mut def_collector = DefCollector::extend(map.krate(),
+    //                                              ii_parent_id,
+    //                                              parent_def_path.clone(),
+    //                                              parent_def_id,
+    //                                              defs);
+    // ii.visit(&mut def_collector);
+    // *map.definitions.borrow_mut() = def_collector.definitions;
 
     let mut collector = NodeCollector::extend(map.krate(),
                                               ii,
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index d63cf875632..6724c0ed8eb 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -122,32 +122,22 @@ pub fn compile_input(sess: &Session,
         let expanded_crate = assign_node_ids(sess, expanded_crate);
         let dep_graph = DepGraph::new(sess.opts.build_dep_graph);
 
-        // TODO
-        // time(sess.time_passes(),
-        //      "external crate/lib resolution",
-        //      || LocalCrateReader::new(sess, &cstore, &defs, &id).read_crates());
+        // Collect defintions for def ids.
+        let defs = time(sess.time_passes(),
+                        "collecting defs",
+                        || hir_map::collect_definitions(&expanded_crate));
 
-        // TODO
-        panic!();
-
-        // TODO CrateMap result
-        // let resolve::CrateMap {
-        //     def_map,
-        //     freevars,
-        //     export_map,
-        //     trait_map,
-        //     glob_map,
-        // } = time(sess.time_passes(),
-        //          "name resolution",
-        //          || resolve::resolve_crate(sess, &hir_map, control.make_glob_map));
+        time(sess.time_passes(),
+             "external crate/lib resolution",
+             || LocalCrateReader::new(sess, &cstore, &defs, &expanded_crate, &id)
+                    .read_crates(&dep_graph));
 
         // Lower ast -> hir.
         let lcx = LoweringContext::new(sess, Some(&expanded_crate));
-        let dep_graph = DepGraph::new(sess.opts.build_dep_graph());
-        let mut hir_forest = time(sess.time_passes(),
-                                  "lowering ast -> hir",
-                                  || hir_map::Forest::new(lower_crate(&lcx, &expanded_crate),
-                                                          dep_graph));
+        let hir_forest = &mut time(sess.time_passes(),
+                                   "lowering ast -> hir",
+                                   || hir_map::Forest::new(lower_crate(&lcx, &expanded_crate),
+                                                           dep_graph));
 
         // Discard MTWT tables that aren't required past lowering to HIR.
         if !sess.opts.debugging_opts.keep_mtwt_tables &&
@@ -156,10 +146,6 @@ pub fn compile_input(sess: &Session,
         }
 
         let arenas = ty::CtxtArenas::new();
-        // Collect defintions for def ids.
-        let defs = time(sess.time_passes(),
-                        "collecting defs",
-                        move || hir_map::collect_defs(hir_forest));
 
         // Construct the HIR map
         let hir_map = time(sess.time_passes(),
@@ -201,10 +187,10 @@ pub fn compile_input(sess: &Session,
         };
 
         phase_3_run_analysis_passes(sess,
-                                    &cstore,
                                     hir_map,
                                     &arenas,
                                     &id,
+                                    control.make_glob_map,
                                     |tcx, mir_map, analysis, result| {
             {
                 // Eventually, we will want to track plugins.
@@ -759,10 +745,10 @@ pub fn assign_node_ids(sess: &Session, krate: ast::Crate) -> ast::Crate {
 /// miscellaneous analysis passes on the crate. Return various
 /// structures carrying the results of the analysis.
 pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
-                                               cstore: &CStore,
                                                hir_map: hir_map::Map<'tcx>,
                                                arenas: &'tcx ty::CtxtArenas<'tcx>,
                                                name: &str,
+                                               make_glob_map: resolve::MakeGlobMap,
                                                f: F)
                                                -> Result<R, usize>
     where F: FnOnce(&TyCtxt<'tcx>, Option<MirMap<'tcx>>, ty::CrateAnalysis, CompileResult) -> R
@@ -787,6 +773,16 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
         })
     })?;
 
+    let resolve::CrateMap {
+        def_map,
+        freevars,
+        export_map,
+        trait_map,
+        glob_map,
+    } = time(sess.time_passes(),
+             "name resolution",
+             || resolve::resolve_crate(sess, &hir_map, make_glob_map));
+
     let mut analysis = ty::CrateAnalysis {
         export_map: export_map,
         access_levels: AccessLevels::default(),
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 228cb8d75af..2e3a477e048 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -179,7 +179,6 @@ impl PpSourceMode {
     }
     fn call_with_pp_support_hir<'tcx, A, B, F>(&self,
                                                sess: &'tcx Session,
-                                               cstore: &CStore,
                                                ast_map: &hir_map::Map<'tcx>,
                                                arenas: &'tcx ty::CtxtArenas<'tcx>,
                                                id: &str,
@@ -206,7 +205,6 @@ impl PpSourceMode {
             }
             PpmTyped => {
                 abort_on_err(driver::phase_3_run_analysis_passes(sess,
-                                                                 cstore,
                                                                  ast_map.clone(),
                                                                  arenas,
                                                                  id,
@@ -737,9 +735,9 @@ pub fn pretty_print_input(sess: Session,
     let dep_graph = DepGraph::new(false);
     let _ignore = dep_graph.in_ignore();
     let ast_map = if compute_ast_map {
+        let defs = hir_map::collect_definitions(&krate);
         hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate), dep_graph.clone());
-        let defs = hir_map::collect_defs(hir_forest);
-        let map = hir_map::map_crate(hir_forest, defs);
+        let map = hir_map::map_crate(&mut hir_forest, defs);
         Some(map)
     } else {
         None
@@ -778,7 +776,6 @@ pub fn pretty_print_input(sess: Session,
         (PpmHir(s), None) => {
             let out: &mut Write = &mut out;
             s.call_with_pp_support_hir(&sess,
-                                       cstore,
                                        &ast_map.unwrap(),
                                        &arenas,
                                        &id,
@@ -800,7 +797,6 @@ pub fn pretty_print_input(sess: Session,
         (PpmHir(s), Some(uii)) => {
             let out: &mut Write = &mut out;
             s.call_with_pp_support_hir(&sess,
-                                       cstore,
                                        &ast_map.unwrap(),
                                        &arenas,
                                        &id,
@@ -841,7 +837,6 @@ pub fn pretty_print_input(sess: Session,
                 None
             };
             abort_on_err(driver::phase_3_run_analysis_passes(&sess,
-                                                             &cstore,
                                                              ast_map,
                                                              &arenas,
                                                              &id,
@@ -888,7 +883,6 @@ pub fn pretty_print_input(sess: Session,
                 Some(code) => {
                     let variants = gather_flowgraph_variants(&sess);
                     abort_on_err(driver::phase_3_run_analysis_passes(&sess,
-                                                                     &cstore,
                                                                      ast_map,
                                                                      &arenas,
                                                                      &id,
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 8ec238f4b24..4ba59a3d7eb 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -18,7 +18,7 @@ use decoder;
 use loader::{self, CratePaths};
 
 use rustc::hir::svh::Svh;
-use rustc::dep_graph::DepNode;
+use rustc::dep_graph::{DepGraph, DepNode};
 use rustc::session::{config, Session};
 use rustc::session::search_paths::PathKind;
 use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate};
@@ -37,15 +37,15 @@ use syntax::parse;
 use syntax::attr;
 use syntax::attr::AttrMetaMethods;
 use syntax::parse::token::InternedString;
-use rustc::hir::intravisit::Visitor;
-use rustc::hir;
+use syntax::visit;
 use log;
 
-pub struct LocalCrateReader<'a, 'b:'a> {
+pub struct LocalCrateReader<'a> {
     sess: &'a Session,
     cstore: &'a CStore,
     creader: CrateReader<'a>,
-    ast_map: &'a hir_map::Map<'b>,
+    krate: &'a ast::Crate,
+    defintions: &'a hir_map::Definitions,
 }
 
 pub struct CrateReader<'a> {
@@ -56,8 +56,8 @@ pub struct CrateReader<'a> {
     local_crate_name: String,
 }
 
-impl<'a, 'b, 'hir> Visitor<'hir> for LocalCrateReader<'a, 'b> {
-    fn visit_item(&mut self, a: &'hir hir::Item) {
+impl<'a, 'ast> visit::Visitor<'ast> for LocalCrateReader<'a> {
+    fn visit_item(&mut self, a: &'ast ast::Item) {
         self.process_item(a);
     }
 }
@@ -80,10 +80,6 @@ fn dump_crates(cstore: &CStore) {
 fn should_link(i: &ast::Item) -> bool {
     !attr::contains_name(&i.attrs, "no_link")
 }
-// Dup for the hir
-fn should_link_hir(i: &hir::Item) -> bool {
-    !attr::contains_name(&i.attrs, "no_link")
-}
 
 struct CrateInfo {
     ident: String,
@@ -181,31 +177,6 @@ impl<'a> CrateReader<'a> {
         }
     }
 
-    // Dup of the above, but for the hir
-    fn extract_crate_info_hir(&self, i: &hir::Item) -> Option<CrateInfo> {
-        match i.node {
-            hir::ItemExternCrate(ref path_opt) => {
-                debug!("resolving extern crate stmt. ident: {} path_opt: {:?}",
-                       i.name, path_opt);
-                let name = match *path_opt {
-                    Some(name) => {
-                        validate_crate_name(Some(self.sess), &name.as_str(),
-                                            Some(i.span));
-                        name.to_string()
-                    }
-                    None => i.name.to_string(),
-                };
-                Some(CrateInfo {
-                    ident: i.name.to_string(),
-                    name: name,
-                    id: i.id,
-                    should_link: should_link_hir(i),
-                })
-            }
-            _ => None
-        }
-    }
-
     fn existing_match(&self, name: &str, hash: Option<&Svh>, kind: PathKind)
                       -> Option<ast::CrateNum> {
         let mut ret = None;
@@ -776,29 +747,30 @@ impl<'a> CrateReader<'a> {
     }
 }
 
-impl<'a, 'b> LocalCrateReader<'a, 'b> {
+impl<'a> LocalCrateReader<'a> {
     pub fn new(sess: &'a Session,
                cstore: &'a CStore,
-               map: &'a hir_map::Map<'b>,
+               defs: &'a hir_map::Definitions,
+               krate: &'a ast::Crate,
                local_crate_name: &str)
-               -> LocalCrateReader<'a, 'b> {
+               -> LocalCrateReader<'a> {
         LocalCrateReader {
             sess: sess,
             cstore: cstore,
             creader: CrateReader::new(sess, cstore, local_crate_name),
-            ast_map: map,
+            krate: krate,
+            defintions: defs,
         }
     }
 
     // Traverses an AST, reading all the information about use'd crates and
     // extern libraries necessary for later resolving, typechecking, linking,
     // etc.
-    pub fn read_crates(&mut self) {
-        let _task = self.ast_map.dep_graph.in_task(DepNode::CrateReader);
-        let krate = self.ast_map.krate();
+    pub fn read_crates(&mut self, dep_graph: &DepGraph) {
+        let _task = dep_graph.in_task(DepNode::CrateReader);
 
-        self.process_crate(krate);
-        krate.visit_all_items(self);
+        self.process_crate(self.krate);
+        visit::walk_crate(self, self.krate);
         self.creader.inject_allocator_crate();
 
         if log_enabled!(log::INFO) {
@@ -811,7 +783,7 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
         self.creader.register_statically_included_foreign_items();
     }
 
-    fn process_crate(&self, c: &hir::Crate) {
+    fn process_crate(&self, c: &ast::Crate) {
         for a in c.attrs.iter().filter(|m| m.name() == "link_args") {
             if let Some(ref linkarg) = a.value_str() {
                 self.cstore.add_used_link_args(&linkarg);
@@ -819,14 +791,14 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
         }
     }
 
-    fn process_item(&mut self, i: &hir::Item) {
+    fn process_item(&mut self, i: &ast::Item) {
         match i.node {
-            hir::ItemExternCrate(_) => {
-                if !should_link_hir(i) {
+            ast::ItemKind::ExternCrate(_) => {
+                if !should_link(i) {
                     return;
                 }
 
-                match self.creader.extract_crate_info_hir(i) {
+                match self.creader.extract_crate_info(i) {
                     Some(info) => {
                         let (cnum, _, _) = self.creader.resolve_crate(&None,
                                                                       &info.ident,
@@ -835,9 +807,9 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
                                                                       i.span,
                                                                       PathKind::Crate,
                                                                       true);
-                        let def_id = self.ast_map.local_def_id(i.id);
+                        let def_id = self.defintions.opt_local_def_id(i.id).unwrap();
 
-                        let len = self.ast_map.def_path(def_id).data.len();
+                        let len = self.defintions.def_path(def_id.index).data.len();
 
                         self.creader.update_extern_crate(cnum,
                                                          ExternCrate {
@@ -851,12 +823,12 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
                     None => ()
                 }
             }
-            hir::ItemForeignMod(ref fm) => self.process_foreign_mod(i, fm),
+            ast::ItemKind::ForeignMod(ref fm) => self.process_foreign_mod(i, fm),
             _ => { }
         }
     }
 
-    fn process_foreign_mod(&mut self, i: &hir::Item, fm: &hir::ForeignMod) {
+    fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod) {
         if fm.abi == Abi::Rust || fm.abi == Abi::RustIntrinsic || fm.abi == Abi::PlatformIntrinsic {
             return;
         }

From 0c37d4bb1d1b8df21e1e4c8a634127cee871f7ab Mon Sep 17 00:00:00 2001
From: Nick Cameron <ncameron@mozilla.com>
Date: Thu, 14 Apr 2016 17:24:30 +1200
Subject: [PATCH 6/9] refactoring

---
 src/librustc/hir/map/collector.rs     | 119 +++++++++++------------
 src/librustc/hir/map/def_collector.rs | 130 +++++++++++---------------
 src/librustc/hir/map/mod.rs           |   5 +-
 3 files changed, 112 insertions(+), 142 deletions(-)

diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index d7fccf03aec..c9d93319c03 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -70,6 +70,13 @@ impl<'ast> NodeCollector<'ast> {
         let entry = MapEntry::from_node(self.parent_node, node);
         self.insert_entry(id, entry);
     }
+
+    fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_id: NodeId, f: F) {
+        let parent_node = self.parent_node;
+        self.parent_node = parent_id;
+        f(self);
+        self.parent_node = parent_node;
+    }
 }
 
 impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
@@ -86,51 +93,48 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
 
         self.insert(i.id, NodeItem(i));
 
-        let parent_node = self.parent_node;
-        self.parent_node = i.id;
-
-        match i.node {
-            ItemEnum(ref enum_definition, _) => {
-                for v in &enum_definition.variants {
-                    self.insert(v.node.data.id(), NodeVariant(v));
-                }
-            }
-            ItemStruct(ref struct_def, _) => {
-                // If this is a tuple-like struct, register the constructor.
-                if !struct_def.is_struct() {
-                    self.insert(struct_def.id(), NodeStructCtor(struct_def));
-                }
-            }
-            ItemTrait(_, _, ref bounds, _) => {
-                for b in bounds.iter() {
-                    if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b {
-                        self.insert(t.trait_ref.ref_id, NodeItem(i));
+        self.with_parent(i.id, |this| {
+            match i.node {
+                ItemEnum(ref enum_definition, _) => {
+                    for v in &enum_definition.variants {
+                        this.insert(v.node.data.id(), NodeVariant(v));
                     }
                 }
-            }
-            ItemUse(ref view_path) => {
-                match view_path.node {
-                    ViewPathList(_, ref paths) => {
-                        for path in paths {
-                            self.insert(path.node.id(), NodeItem(i));
+                ItemStruct(ref struct_def, _) => {
+                    // If this is a tuple-like struct, register the constructor.
+                    if !struct_def.is_struct() {
+                        this.insert(struct_def.id(), NodeStructCtor(struct_def));
+                    }
+                }
+                ItemTrait(_, _, ref bounds, _) => {
+                    for b in bounds.iter() {
+                        if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b {
+                            this.insert(t.trait_ref.ref_id, NodeItem(i));
                         }
                     }
-                    _ => ()
                 }
+                ItemUse(ref view_path) => {
+                    match view_path.node {
+                        ViewPathList(_, ref paths) => {
+                            for path in paths {
+                                this.insert(path.node.id(), NodeItem(i));
+                            }
+                        }
+                        _ => ()
+                    }
+                }
+                _ => {}
             }
-            _ => {}
-        }
-        intravisit::walk_item(self, i);
-        self.parent_node = parent_node;
+            intravisit::walk_item(this, i);
+        });
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
         self.insert(foreign_item.id, NodeForeignItem(foreign_item));
 
-        let parent_node = self.parent_node;
-        self.parent_node = foreign_item.id;
-        intravisit::walk_foreign_item(self, foreign_item);
-        self.parent_node = parent_node;
+        self.with_parent(foreign_item.id, |this| {
+            intravisit::walk_foreign_item(this, foreign_item);
+        });
     }
 
     fn visit_generics(&mut self, generics: &'ast Generics) {
@@ -144,50 +148,42 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
     fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
         self.insert(ti.id, NodeTraitItem(ti));
 
-        let parent_node = self.parent_node;
-        self.parent_node = ti.id;
-
-        intravisit::walk_trait_item(self, ti);
-
-        self.parent_node = parent_node;
+        self.with_parent(ti.id, |this| {
+            intravisit::walk_trait_item(this, ti);
+        });
     }
 
     fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
         self.insert(ii.id, NodeImplItem(ii));
 
-        let parent_node = self.parent_node;
-        self.parent_node = ii.id;
-
-        intravisit::walk_impl_item(self, ii);
-
-        self.parent_node = parent_node;
+        self.with_parent(ii.id, |this| {
+            intravisit::walk_impl_item(this, ii);
+        });
     }
 
     fn visit_pat(&mut self, pat: &'ast Pat) {
         self.insert(pat.id, NodeLocal(pat));
 
-        let parent_node = self.parent_node;
-        self.parent_node = pat.id;
-        intravisit::walk_pat(self, pat);
-        self.parent_node = parent_node;
+        self.with_parent(pat.id, |this| {
+            intravisit::walk_pat(this, pat);
+        });
     }
 
     fn visit_expr(&mut self, expr: &'ast Expr) {
         self.insert(expr.id, NodeExpr(expr));
 
-        let parent_node = self.parent_node;
-        self.parent_node = expr.id;
-        intravisit::walk_expr(self, expr);
-        self.parent_node = parent_node;
+        self.with_parent(expr.id, |this| {
+            intravisit::walk_expr(this, expr);
+        });
     }
 
     fn visit_stmt(&mut self, stmt: &'ast Stmt) {
         let id = stmt.node.id();
         self.insert(id, NodeStmt(stmt));
-        let parent_node = self.parent_node;
-        self.parent_node = id;
-        intravisit::walk_stmt(self, stmt);
-        self.parent_node = parent_node;
+
+        self.with_parent(id, |this| {
+            intravisit::walk_stmt(this, stmt);
+        });
     }
 
     fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl,
@@ -198,10 +194,9 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
 
     fn visit_block(&mut self, block: &'ast Block) {
         self.insert(block.id, NodeBlock(block));
-        let parent_node = self.parent_node;
-        self.parent_node = block.id;
-        intravisit::walk_block(self, block);
-        self.parent_node = parent_node;
+        self.with_parent(block.id, |this| {
+            intravisit::walk_block(this, block);
+        });
     }
 
     fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index a259c5a0f31..9d6027932f6 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -16,16 +16,14 @@ use syntax::ast::*;
 use syntax::visit;
 
 /// Creates def ids for nodes in the HIR.
-pub struct DefCollector<'ast> {
-    pub krate: &'ast Crate,
+pub struct DefCollector {
     pub definitions: Definitions,
     pub parent_def: Option<DefIndex>,
 }
 
-impl<'ast> DefCollector<'ast> {
-    pub fn root(krate: &'ast Crate) -> DefCollector<'ast> {
+impl DefCollector {
+    pub fn root() -> DefCollector {
         let mut collector = DefCollector {
-            krate: krate,
             definitions: Definitions::new(),
             parent_def: None,
         };
@@ -37,14 +35,12 @@ impl<'ast> DefCollector<'ast> {
         collector
     }
 
-    pub fn extend(krate: &'ast Crate,
-                  parent_node: NodeId,
+    pub fn extend(parent_node: NodeId,
                   parent_def_path: DefPath,
                   parent_def_id: DefId,
                   definitions: Definitions)
-                  -> DefCollector<'ast> {
+                  -> DefCollector {
         let mut collector = DefCollector {
-            krate: krate,
             parent_def: None,
             definitions: definitions,
         };
@@ -78,9 +74,16 @@ impl<'ast> DefCollector<'ast> {
                               -> DefIndex {
         self.definitions.create_def_with_parent(parent, node_id, data)
     }
+
+    fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {
+        let parent = self.parent_def;
+        self.parent_def = Some(parent_def);
+        f(self);
+        self.parent_def = parent;
+    }
 }
 
-impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
+impl<'ast> visit::Visitor<'ast> for DefCollector {
     fn visit_item(&mut self, i: &'ast Item) {
         debug!("visit_item: {:?}", i);
 
@@ -98,60 +101,55 @@ impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
             ItemKind::Mac(..) => DefPathData::MacroDef(i.ident.name),
             ItemKind::Use(..) => DefPathData::Misc,
         };
-
         let def = self.create_def(i.id, def_data);
 
-        let parent_def = self.parent_def;
-        self.parent_def = Some(def);
+        self.with_parent(def, |this| {
+            match i.node {
+                ItemKind::Enum(ref enum_definition, _) => {
+                    for v in &enum_definition.variants {
+                        let variant_def_index =
+                            this.create_def(v.node.data.id(),
+                                            DefPathData::EnumVariant(v.node.name.name));
 
-        match i.node {
-            ItemKind::Enum(ref enum_definition, _) => {
-                for v in &enum_definition.variants {
-                    let variant_def_index =
-                        self.create_def(v.node.data.id(),
-                                        DefPathData::EnumVariant(v.node.name.name));
-
-                    for field in v.node.data.fields() {
-                        if let Some(ident) = field.ident {
-                            self.create_def_with_parent(Some(variant_def_index),
-                                                        field.id,
-                                                        DefPathData::Field(ident.name));
+                        for field in v.node.data.fields() {
+                            if let Some(ident) = field.ident {
+                                this.create_def_with_parent(Some(variant_def_index),
+                                                            field.id,
+                                                            DefPathData::Field(ident.name));
+                            }
                         }
                     }
                 }
-            }
-            ItemKind::Struct(ref struct_def, _) => {
-                // If this is a tuple-like struct, register the constructor.
-                if !struct_def.is_struct() {
-                    self.create_def(struct_def.id(),
-                                    DefPathData::StructCtor);
-                }
+                ItemKind::Struct(ref struct_def, _) => {
+                    // If this is a tuple-like struct, register the constructor.
+                    if !struct_def.is_struct() {
+                        this.create_def(struct_def.id(),
+                                        DefPathData::StructCtor);
+                    }
 
-                for field in struct_def.fields() {
-                    if let Some(ident) = field.ident {
-                        self.create_def(field.id, DefPathData::Field(ident.name));
+                    for field in struct_def.fields() {
+                        if let Some(ident) = field.ident {
+                            this.create_def(field.id, DefPathData::Field(ident.name));
+                        }
                     }
                 }
+                _ => {}
             }
-            _ => {}
-        }
-        visit::walk_item(self, i);
-        self.parent_def = parent_def;
+            visit::walk_item(this, i);
+        });
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
         let def = self.create_def(foreign_item.id, DefPathData::ValueNs(foreign_item.ident.name));
 
-        let parent_def = self.parent_def;
-        self.parent_def = Some(def);
-        visit::walk_foreign_item(self, foreign_item);
-        self.parent_def = parent_def;
+        self.with_parent(def, |this| {
+            visit::walk_foreign_item(this, foreign_item);
+        });
     }
 
     fn visit_generics(&mut self, generics: &'ast Generics) {
         for ty_param in generics.ty_params.iter() {
-            self.create_def(ty_param.id,
-                            DefPathData::TypeParam(ty_param.ident.name));
+            self.create_def(ty_param.id, DefPathData::TypeParam(ty_param.ident.name));
         }
 
         visit::walk_generics(self, generics);
@@ -165,20 +163,13 @@ impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
         };
 
         let def = self.create_def(ti.id, def_data);
-
-        let parent_def = self.parent_def;
-        self.parent_def = Some(def);
-
-        match ti.node {
-            TraitItemKind::Const(_, Some(ref expr)) => {
-                self.create_def(expr.id, DefPathData::Initializer);
+        self.with_parent(def, |this| {
+            if let TraitItemKind::Const(_, Some(ref expr)) = ti.node {
+                this.create_def(expr.id, DefPathData::Initializer);
             }
-            _ => { }
-        }
 
-        visit::walk_trait_item(self, ti);
-
-        self.parent_def = parent_def;
+            visit::walk_trait_item(this, ti);
+        });
     }
 
     fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
@@ -190,20 +181,13 @@ impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
         };
 
         let def = self.create_def(ii.id, def_data);
-
-        let parent_def = self.parent_def;
-        self.parent_def = Some(def);
-
-        match ii.node {
-            ImplItemKind::Const(_, ref expr) => {
-                self.create_def(expr.id, DefPathData::Initializer);
+        self.with_parent(def, |this| {
+            if let ImplItemKind::Const(_, ref expr) = ii.node {
+                this.create_def(expr.id, DefPathData::Initializer);
             }
-            _ => { }
-        }
 
-        visit::walk_impl_item(self, ii);
-
-        self.parent_def = parent_def;
+            visit::walk_impl_item(this, ii);
+        });
     }
 
     fn visit_pat(&mut self, pat: &'ast Pat) {
@@ -234,14 +218,6 @@ impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
         self.parent_def = parent_def;
     }
 
-    fn visit_stmt(&mut self, stmt: &'ast Stmt) {
-        visit::walk_stmt(self, stmt);
-    }
-
-    fn visit_block(&mut self, block: &'ast Block) {
-        visit::walk_block(self, block);
-    }
-
     fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
         self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
     }
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index b1954255278..a505ad19889 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -784,7 +784,7 @@ impl<F: FoldOps> Folder for IdAndSpanUpdater<F> {
 }
 
 pub fn collect_definitions<'ast>(krate: &'ast ast::Crate) -> Definitions {
-    let mut def_collector = DefCollector::root(krate);
+    let mut def_collector = DefCollector::root();
     visit::walk_crate(&mut def_collector, krate);
     def_collector.definitions
 }
@@ -845,8 +845,7 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
 
     // TODO need to save defs in metadata :-(
     // let defs = mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new());
-    // let mut def_collector = DefCollector::extend(map.krate(),
-    //                                              ii_parent_id,
+    // let mut def_collector = DefCollector::extend(ii_parent_id,
     //                                              parent_def_path.clone(),
     //                                              parent_def_id,
     //                                              defs);

From 744be0b5aac8c06c60dabac3a7802a8117c946b2 Mon Sep 17 00:00:00 2001
From: Nick Cameron <ncameron@mozilla.com>
Date: Thu, 14 Apr 2016 18:04:55 +1200
Subject: [PATCH 7/9] HIR visitor for DefCollector

So that we can work with inlined HIR from metadata.
---
 src/librustc/hir/map/def_collector.rs | 174 +++++++++++++++++++++++++-
 src/librustc/hir/map/mod.rs           |  15 ++-
 2 files changed, 175 insertions(+), 14 deletions(-)

diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index 9d6027932f6..f8d0243548f 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -10,20 +10,28 @@
 
 use super::*;
 
+use hir;
+use hir::intravisit;
 use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
 
+use middle::cstore::InlinedItem;
+
 use syntax::ast::*;
 use syntax::visit;
 
 /// Creates def ids for nodes in the HIR.
-pub struct DefCollector {
+pub struct DefCollector<'ast> {
+    // If we are walking HIR (c.f., AST), we need to keep a reference to the
+    // crate.
+    hir_crate: Option<&'ast hir::Crate>,
     pub definitions: Definitions,
-    pub parent_def: Option<DefIndex>,
+    parent_def: Option<DefIndex>,
 }
 
-impl DefCollector {
-    pub fn root() -> DefCollector {
+impl<'ast> DefCollector<'ast> {
+    pub fn root() -> DefCollector<'ast> {
         let mut collector = DefCollector {
+            hir_crate: None,
             definitions: Definitions::new(),
             parent_def: None,
         };
@@ -39,8 +47,9 @@ impl DefCollector {
                   parent_def_path: DefPath,
                   parent_def_id: DefId,
                   definitions: Definitions)
-                  -> DefCollector {
+                  -> DefCollector<'ast> {
         let mut collector = DefCollector {
+            hir_crate: None,
             parent_def: None,
             definitions: definitions,
         };
@@ -57,6 +66,11 @@ impl DefCollector {
         collector
     }
 
+    pub fn walk_item(&mut self, ii: &'ast InlinedItem, krate: &'ast hir::Crate) {
+        self.hir_crate = Some(krate);
+        ii.visit(self);
+    }
+
     fn parent_def(&self) -> Option<DefIndex> {
         self.parent_def
     }
@@ -83,7 +97,7 @@ impl DefCollector {
     }
 }
 
-impl<'ast> visit::Visitor<'ast> for DefCollector {
+impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
     fn visit_item(&mut self, i: &'ast Item) {
         debug!("visit_item: {:?}", i);
 
@@ -226,3 +240,151 @@ impl<'ast> visit::Visitor<'ast> for DefCollector {
         self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.ident.name));
     }
 }
+
+// We walk the HIR rather than the AST when reading items from metadata.
+impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
+    /// Because we want to track parent items and so forth, enable
+    /// deep walking so that we walk nested items in the context of
+    /// their outer items.
+    fn visit_nested_item(&mut self, item_id: hir::ItemId) {
+        debug!("visit_nested_item: {:?}", item_id);
+        let item = self.hir_crate.unwrap().item(item_id.id);
+        self.visit_item(item)
+    }
+
+    fn visit_item(&mut self, i: &'ast hir::Item) {
+        debug!("visit_item: {:?}", i);
+
+        // Pick the def data. This need not be unique, but the more
+        // information we encapsulate into
+        let def_data = match i.node {
+            hir::ItemDefaultImpl(..) | hir::ItemImpl(..) =>
+                DefPathData::Impl,
+            hir::ItemEnum(..) | hir::ItemStruct(..) | hir::ItemTrait(..) |
+            hir::ItemExternCrate(..) | hir::ItemMod(..) | hir::ItemForeignMod(..) |
+            hir::ItemTy(..) =>
+                DefPathData::TypeNs(i.name),
+            hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) =>
+                DefPathData::ValueNs(i.name),
+            hir::ItemUse(..) => DefPathData::Misc,
+        };
+        let def = self.create_def(i.id, def_data);
+
+        self.with_parent(def, |this| {
+            match i.node {
+                hir::ItemEnum(ref enum_definition, _) => {
+                    for v in &enum_definition.variants {
+                        let variant_def_index =
+                            this.create_def(v.node.data.id(),
+                                            DefPathData::EnumVariant(v.node.name));
+
+                        for field in v.node.data.fields() {
+                            this.create_def_with_parent(Some(variant_def_index),
+                                                        field.id,
+                                                        DefPathData::Field(field.name));
+                        }
+                    }
+                }
+                hir::ItemStruct(ref struct_def, _) => {
+                    // If this is a tuple-like struct, register the constructor.
+                    if !struct_def.is_struct() {
+                        this.create_def(struct_def.id(),
+                                        DefPathData::StructCtor);
+                    }
+
+                    for field in struct_def.fields() {
+                        this.create_def(field.id, DefPathData::Field(field.name));
+                    }
+                }
+                _ => {}
+            }
+            intravisit::walk_item(this, i);
+        });
+    }
+
+    fn visit_foreign_item(&mut self, foreign_item: &'ast hir::ForeignItem) {
+        let def = self.create_def(foreign_item.id, DefPathData::ValueNs(foreign_item.name));
+
+        self.with_parent(def, |this| {
+            intravisit::walk_foreign_item(this, foreign_item);
+        });
+    }
+
+    fn visit_generics(&mut self, generics: &'ast hir::Generics) {
+        for ty_param in generics.ty_params.iter() {
+            self.create_def(ty_param.id, DefPathData::TypeParam(ty_param.name));
+        }
+
+        intravisit::walk_generics(self, generics);
+    }
+
+    fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
+        let def_data = match ti.node {
+            hir::MethodTraitItem(..) | hir::ConstTraitItem(..) =>
+                DefPathData::ValueNs(ti.name),
+            hir::TypeTraitItem(..) => DefPathData::TypeNs(ti.name),
+        };
+
+        let def = self.create_def(ti.id, def_data);
+        self.with_parent(def, |this| {
+            if let hir::ConstTraitItem(_, Some(ref expr)) = ti.node {
+                this.create_def(expr.id, DefPathData::Initializer);
+            }
+
+            intravisit::walk_trait_item(this, ti);
+        });
+    }
+
+    fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
+        let def_data = match ii.node {
+            hir::ImplItemKind::Method(..) | hir::ImplItemKind::Const(..) =>
+                DefPathData::ValueNs(ii.name),
+            hir::ImplItemKind::Type(..) => DefPathData::TypeNs(ii.name),
+        };
+
+        let def = self.create_def(ii.id, def_data);
+        self.with_parent(def, |this| {
+            if let hir::ImplItemKind::Const(_, ref expr) = ii.node {
+                this.create_def(expr.id, DefPathData::Initializer);
+            }
+
+            intravisit::walk_impl_item(this, ii);
+        });
+    }
+
+    fn visit_pat(&mut self, pat: &'ast hir::Pat) {
+        let maybe_binding = match pat.node {
+            hir::PatKind::Ident(_, id, _) => Some(id.node),
+            _ => None
+        };
+
+        let parent_def = self.parent_def;
+        if let Some(id) = maybe_binding {
+            let def = self.create_def(pat.id, DefPathData::Binding(id.name));
+            self.parent_def = Some(def);
+        }
+
+        intravisit::walk_pat(self, pat);
+        self.parent_def = parent_def;
+    }
+
+    fn visit_expr(&mut self, expr: &'ast hir::Expr) {
+        let parent_def = self.parent_def;
+
+        if let hir::ExprClosure(..) = expr.node {
+            let def = self.create_def(expr.id, DefPathData::ClosureExpr);
+            self.parent_def = Some(def);
+        }
+
+        intravisit::walk_expr(self, expr);
+        self.parent_def = parent_def;
+    }
+
+    fn visit_lifetime_def(&mut self, def: &'ast hir::LifetimeDef) {
+        self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
+    }
+
+    fn visit_macro_def(&mut self, macro_def: &'ast hir::MacroDef) {
+        self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
+    }
+}
\ No newline at end of file
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index a505ad19889..1d0c40646b5 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -843,14 +843,13 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
     let ii = map.forest.inlined_items.alloc(ii);
     let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
 
-    // TODO need to save defs in metadata :-(
-    // let defs = mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new());
-    // let mut def_collector = DefCollector::extend(ii_parent_id,
-    //                                              parent_def_path.clone(),
-    //                                              parent_def_id,
-    //                                              defs);
-    // ii.visit(&mut def_collector);
-    // *map.definitions.borrow_mut() = def_collector.definitions;
+    let defs = mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new());
+    let mut def_collector = DefCollector::extend(ii_parent_id,
+                                                 parent_def_path.clone(),
+                                                 parent_def_id,
+                                                 defs);
+    def_collector.walk_item(ii, map.krate());
+    *map.definitions.borrow_mut() = def_collector.definitions;
 
     let mut collector = NodeCollector::extend(map.krate(),
                                               ii,

From 1d5a29cf0e40c412bb2e090aadcf3ebfb1d5fa13 Mon Sep 17 00:00:00 2001
From: Nick Cameron <ncameron@mozilla.com>
Date: Mon, 18 Apr 2016 10:30:55 +1200
Subject: [PATCH 8/9] debugging, misc fixes

---
 src/librustc/hir/lowering.rs               | 218 ++++++++++++++-------
 src/librustc/hir/map/collector.rs          |   7 +-
 src/librustc/hir/map/def_collector.rs      |  46 ++---
 src/librustc/hir/map/mod.rs                |   8 +-
 src/librustc_driver/driver.rs              |   9 +-
 src/librustc_driver/lib.rs                 |  11 +-
 src/librustc_driver/pretty.rs              |  19 +-
 src/librustc_driver/test.rs                |  12 +-
 src/librustc_metadata/astencode.rs         |   8 +-
 src/librustc_metadata/creader.rs           |  11 +-
 src/librustc_save_analysis/csv_dumper.rs   |   4 +-
 src/librustc_save_analysis/dump_visitor.rs |  23 +--
 src/librustc_save_analysis/lib.rs          |  11 +-
 src/librustc_save_analysis/span_utils.rs   |   2 +
 src/librustdoc/core.rs                     |  13 +-
 src/librustdoc/test.rs                     |   8 +-
 src/test/run-make/execution-engine/test.rs |  12 +-
 17 files changed, 260 insertions(+), 162 deletions(-)

diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 7c476657041..0a01cc91f0e 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -62,6 +62,9 @@
 // in the HIR, especially for multiple identifiers.
 
 use hir;
+use hir::map::Definitions;
+use hir::map::definitions::DefPathData;
+use hir::def_id::DefIndex;
 
 use std::collections::BTreeMap;
 use std::collections::HashMap;
@@ -92,10 +95,20 @@ pub struct LoweringContext<'a> {
     // A copy of cached_id, but is also set to an id while a node is lowered for
     // the first time.
     gensym_key: Cell<u32>,
+    // We must keep the set of definitions up to date as we add nodes that
+    // weren't in the AST.
+    definitions: Option<&'a RefCell<Definitions>>,
+    // As we walk the AST we must keep track of the current 'parent' def id (in
+    // the form of a DefIndex) so that if we create a new node which introduces
+    // a definition, then we can properly create the def id.
+    parent_def: Cell<Option<DefIndex>>,
 }
 
 impl<'a, 'hir> LoweringContext<'a> {
-    pub fn new(id_assigner: &'a NodeIdAssigner, c: Option<&Crate>) -> LoweringContext<'a> {
+    pub fn new(id_assigner: &'a NodeIdAssigner,
+               c: Option<&Crate>,
+               defs: &'a RefCell<Definitions>)
+               -> LoweringContext<'a> {
         let crate_root = c.and_then(|c| {
             if std_inject::no_core(c) {
                 None
@@ -113,6 +126,23 @@ impl<'a, 'hir> LoweringContext<'a> {
             cached_id: Cell::new(0),
             gensym_cache: RefCell::new(HashMap::new()),
             gensym_key: Cell::new(0),
+            definitions: Some(defs),
+            parent_def: Cell::new(None),
+        }
+    }
+
+    // Only use this when you want a LoweringContext for testing and won't look
+    // up def ids for anything created during lowering.
+    pub fn testing_context(id_assigner: &'a NodeIdAssigner) -> LoweringContext<'a> {
+        LoweringContext {
+            crate_root: None,
+            id_cache: RefCell::new(HashMap::new()),
+            id_assigner: id_assigner,
+            cached_id: Cell::new(0),
+            gensym_cache: RefCell::new(HashMap::new()),
+            gensym_key: Cell::new(0),
+            definitions: None,
+            parent_def: Cell::new(None),
         }
     }
 
@@ -146,6 +176,25 @@ impl<'a, 'hir> LoweringContext<'a> {
     fn diagnostic(&self) -> &Handler {
         self.id_assigner.diagnostic()
     }
+
+    fn with_parent_def<T, F: FnOnce() -> T>(&self, parent_id: NodeId, f: F) -> T {
+        if self.definitions.is_none() {
+            // This should only be used for testing.
+            return f();
+        }
+
+        let old_def = self.parent_def.get();
+        self.parent_def.set(Some(self.get_def(parent_id)));
+        let result = f();
+        self.parent_def.set(old_def);
+
+        result
+    }
+
+    fn get_def(&self, id: NodeId) -> DefIndex {
+        let defs = self.definitions.unwrap().borrow();
+        defs.opt_def_index(id).unwrap()
+    }
 }
 
 // Utility fn for setting and unsetting the cached id.
@@ -733,47 +782,51 @@ pub fn lower_item_kind(lctx: &LoweringContext, i: &ItemKind) -> hir::Item_ {
 }
 
 pub fn lower_trait_item(lctx: &LoweringContext, i: &TraitItem) -> hir::TraitItem {
-    hir::TraitItem {
-        id: i.id,
-        name: i.ident.name,
-        attrs: lower_attrs(lctx, &i.attrs),
-        node: match i.node {
-            TraitItemKind::Const(ref ty, ref default) => {
-                hir::ConstTraitItem(lower_ty(lctx, ty),
-                                    default.as_ref().map(|x| lower_expr(lctx, x)))
-            }
-            TraitItemKind::Method(ref sig, ref body) => {
-                hir::MethodTraitItem(lower_method_sig(lctx, sig),
-                                     body.as_ref().map(|x| lower_block(lctx, x)))
-            }
-            TraitItemKind::Type(ref bounds, ref default) => {
-                hir::TypeTraitItem(lower_bounds(lctx, bounds),
-                                   default.as_ref().map(|x| lower_ty(lctx, x)))
-            }
-        },
-        span: i.span,
-    }
+    lctx.with_parent_def(i.id, || {
+        hir::TraitItem {
+            id: i.id,
+            name: i.ident.name,
+            attrs: lower_attrs(lctx, &i.attrs),
+            node: match i.node {
+                TraitItemKind::Const(ref ty, ref default) => {
+                    hir::ConstTraitItem(lower_ty(lctx, ty),
+                                        default.as_ref().map(|x| lower_expr(lctx, x)))
+                }
+                TraitItemKind::Method(ref sig, ref body) => {
+                    hir::MethodTraitItem(lower_method_sig(lctx, sig),
+                                         body.as_ref().map(|x| lower_block(lctx, x)))
+                }
+                TraitItemKind::Type(ref bounds, ref default) => {
+                    hir::TypeTraitItem(lower_bounds(lctx, bounds),
+                                       default.as_ref().map(|x| lower_ty(lctx, x)))
+                }
+            },
+            span: i.span,
+        }
+    })
 }
 
 pub fn lower_impl_item(lctx: &LoweringContext, i: &ImplItem) -> hir::ImplItem {
-    hir::ImplItem {
-        id: i.id,
-        name: i.ident.name,
-        attrs: lower_attrs(lctx, &i.attrs),
-        vis: lower_visibility(lctx, &i.vis),
-        defaultness: lower_defaultness(lctx, i.defaultness),
-        node: match i.node {
-            ImplItemKind::Const(ref ty, ref expr) => {
-                hir::ImplItemKind::Const(lower_ty(lctx, ty), lower_expr(lctx, expr))
-            }
-            ImplItemKind::Method(ref sig, ref body) => {
-                hir::ImplItemKind::Method(lower_method_sig(lctx, sig), lower_block(lctx, body))
-            }
-            ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(lower_ty(lctx, ty)),
-            ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"),
-        },
-        span: i.span,
-    }
+    lctx.with_parent_def(i.id, || {
+        hir::ImplItem {
+            id: i.id,
+            name: i.ident.name,
+            attrs: lower_attrs(lctx, &i.attrs),
+            vis: lower_visibility(lctx, &i.vis),
+            defaultness: lower_defaultness(lctx, i.defaultness),
+            node: match i.node {
+                ImplItemKind::Const(ref ty, ref expr) => {
+                    hir::ImplItemKind::Const(lower_ty(lctx, ty), lower_expr(lctx, expr))
+                }
+                ImplItemKind::Method(ref sig, ref body) => {
+                    hir::ImplItemKind::Method(lower_method_sig(lctx, sig), lower_block(lctx, body))
+                }
+                ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(lower_ty(lctx, ty)),
+                ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"),
+            },
+            span: i.span,
+        }
+    })
 }
 
 pub fn lower_mod(lctx: &LoweringContext, m: &Mod) -> hir::Mod {
@@ -831,7 +884,9 @@ pub fn lower_item_id(_lctx: &LoweringContext, i: &Item) -> hir::ItemId {
 }
 
 pub fn lower_item(lctx: &LoweringContext, i: &Item) -> hir::Item {
-    let node = lower_item_kind(lctx, &i.node);
+    let node = lctx.with_parent_def(i.id, || {
+        lower_item_kind(lctx, &i.node)
+    });
 
     hir::Item {
         id: i.id,
@@ -844,21 +899,23 @@ pub fn lower_item(lctx: &LoweringContext, i: &Item) -> hir::Item {
 }
 
 pub fn lower_foreign_item(lctx: &LoweringContext, i: &ForeignItem) -> hir::ForeignItem {
-    hir::ForeignItem {
-        id: i.id,
-        name: i.ident.name,
-        attrs: lower_attrs(lctx, &i.attrs),
-        node: match i.node {
-            ForeignItemKind::Fn(ref fdec, ref generics) => {
-                hir::ForeignItemFn(lower_fn_decl(lctx, fdec), lower_generics(lctx, generics))
-            }
-            ForeignItemKind::Static(ref t, m) => {
-                hir::ForeignItemStatic(lower_ty(lctx, t), m)
-            }
-        },
-        vis: lower_visibility(lctx, &i.vis),
-        span: i.span,
-    }
+    lctx.with_parent_def(i.id, || {
+        hir::ForeignItem {
+            id: i.id,
+            name: i.ident.name,
+            attrs: lower_attrs(lctx, &i.attrs),
+            node: match i.node {
+                ForeignItemKind::Fn(ref fdec, ref generics) => {
+                    hir::ForeignItemFn(lower_fn_decl(lctx, fdec), lower_generics(lctx, generics))
+                }
+                ForeignItemKind::Static(ref t, m) => {
+                    hir::ForeignItemStatic(lower_ty(lctx, t), m)
+                }
+            },
+            vis: lower_visibility(lctx, &i.vis),
+            span: i.span,
+        }
+    })
 }
 
 pub fn lower_method_sig(lctx: &LoweringContext, sig: &MethodSig) -> hir::MethodSig {
@@ -926,9 +983,11 @@ pub fn lower_pat(lctx: &LoweringContext, p: &Pat) -> P<hir::Pat> {
         node: match p.node {
             PatKind::Wild => hir::PatKind::Wild,
             PatKind::Ident(ref binding_mode, pth1, ref sub) => {
-                hir::PatKind::Ident(lower_binding_mode(lctx, binding_mode),
-                              respan(pth1.span, lower_ident(lctx, pth1.node)),
-                              sub.as_ref().map(|x| lower_pat(lctx, x)))
+                lctx.with_parent_def(p.id, || {
+                    hir::PatKind::Ident(lower_binding_mode(lctx, binding_mode),
+                                  respan(pth1.span, lower_ident(lctx, pth1.node)),
+                                  sub.as_ref().map(|x| lower_pat(lctx, x)))
+                })
             }
             PatKind::Lit(ref e) => hir::PatKind::Lit(lower_expr(lctx, e)),
             PatKind::TupleStruct(ref pth, ref pats) => {
@@ -1202,9 +1261,11 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                                hir::MatchSource::Normal)
             }
             ExprKind::Closure(capture_clause, ref decl, ref body) => {
-                hir::ExprClosure(lower_capture_clause(lctx, capture_clause),
-                                 lower_fn_decl(lctx, decl),
-                                 lower_block(lctx, body))
+                lctx.with_parent_def(e.id, || {
+                    hir::ExprClosure(lower_capture_clause(lctx, capture_clause),
+                                     lower_fn_decl(lctx, decl),
+                                     lower_block(lctx, body))
+                })
             }
             ExprKind::Block(ref blk) => hir::ExprBlock(lower_block(lctx, blk)),
             ExprKind::Assign(ref el, ref er) => {
@@ -1602,7 +1663,12 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                     // `{ let _result = ...; _result }`
                     // underscore prevents an unused_variables lint if the head diverges
                     let result_ident = lctx.str_to_ident("_result");
-                    let let_stmt = stmt_let(lctx, e.span, false, result_ident, match_expr, None);
+                    let let_stmt = stmt_let(lctx,
+                                            e.span,
+                                            false,
+                                            result_ident,
+                                            match_expr,
+                                            None);
                     let result = expr_ident(lctx, e.span, result_ident, None);
                     let block = block_all(lctx, e.span, hir_vec![let_stmt], Some(result));
                     // add the attributes to the outer returned expr node
@@ -1655,7 +1721,8 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                             let err_ctor = expr_path(lctx, path, None);
                             expr_call(lctx, e.span, err_ctor, hir_vec![from_expr], None)
                         };
-                        let err_pat = pat_err(lctx, e.span, pat_ident(lctx, e.span, err_ident));
+                        let err_pat = pat_err(lctx, e.span,
+                                              pat_ident(lctx, e.span, err_ident));
                         let ret_expr = expr(lctx, e.span,
                                             hir::Expr_::ExprRet(Some(err_expr)), None);
 
@@ -1938,12 +2005,22 @@ fn pat_ident_binding_mode(lctx: &LoweringContext,
                           bm: hir::BindingMode)
                           -> P<hir::Pat> {
     let pat_ident = hir::PatKind::Ident(bm,
-                                  Spanned {
-                                      span: span,
-                                      node: ident,
-                                  },
-                                  None);
-    pat(lctx, span, pat_ident)
+                                        Spanned {
+                                            span: span,
+                                            node: ident,
+                                        },
+                                        None);
+
+    let pat = pat(lctx, span, pat_ident);
+
+    if let Some(defs) = lctx.definitions {
+        let mut defs = defs.borrow_mut();
+        defs.create_def_with_parent(lctx.parent_def.get(),
+                                    pat.id,
+                                    DefPathData::Binding(ident.name));
+    }
+
+    pat
 }
 
 fn pat_wild(lctx: &LoweringContext, span: Span) -> P<hir::Pat> {
@@ -2130,7 +2207,8 @@ mod test {
         let ast_in = quote_expr!(&cx, in HEAP { foo() });
         let ast_in = assigner.fold_expr(ast_in);
 
-        let lctx = LoweringContext::new(&assigner, None);
+        let lctx = LoweringContext::testing_context(&assigner);
+
         let hir1 = lower_expr(&lctx, &ast_if_let);
         let hir2 = lower_expr(&lctx, &ast_if_let);
         assert!(hir1 == hir2);
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index c9d93319c03..9f55f46541c 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -162,7 +162,12 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
     }
 
     fn visit_pat(&mut self, pat: &'ast Pat) {
-        self.insert(pat.id, NodeLocal(pat));
+        let node = if let PatKind::Ident(..) = pat.node {
+            NodeLocal(pat)
+        } else {
+            NodePat(pat)
+        };
+        self.insert(pat.id, node);
 
         self.with_parent(pat.id, |this| {
             intravisit::walk_pat(this, pat);
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index f8d0243548f..b2456f4ab87 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -18,6 +18,7 @@ use middle::cstore::InlinedItem;
 
 use syntax::ast::*;
 use syntax::visit;
+use syntax::parse::token;
 
 /// Creates def ids for nodes in the HIR.
 pub struct DefCollector<'ast> {
@@ -35,8 +36,9 @@ impl<'ast> DefCollector<'ast> {
             definitions: Definitions::new(),
             parent_def: None,
         };
-        let result = collector.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot);
-        assert_eq!(result, CRATE_DEF_INDEX);
+        let root = collector.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot);
+        assert_eq!(root, CRATE_DEF_INDEX);
+        collector.parent_def = Some(root);
 
         collector.create_def_with_parent(Some(CRATE_DEF_INDEX), DUMMY_NODE_ID, DefPathData::Misc);
 
@@ -125,12 +127,12 @@ impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
                             this.create_def(v.node.data.id(),
                                             DefPathData::EnumVariant(v.node.name.name));
 
-                        for field in v.node.data.fields() {
-                            if let Some(ident) = field.ident {
-                                this.create_def_with_parent(Some(variant_def_index),
-                                                            field.id,
-                                                            DefPathData::Field(ident.name));
-                            }
+                        for (index, field) in v.node.data.fields().iter().enumerate() {
+                            let name = field.ident.map(|ident| ident.name)
+                                .unwrap_or(token::intern(&index.to_string()));
+                            this.create_def_with_parent(Some(variant_def_index),
+                                                        field.id,
+                                                        DefPathData::Field(name));
                         }
                     }
                 }
@@ -141,10 +143,10 @@ impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
                                         DefPathData::StructCtor);
                     }
 
-                    for field in struct_def.fields() {
-                        if let Some(ident) = field.ident {
-                            this.create_def(field.id, DefPathData::Field(ident.name));
-                        }
+                    for (index, field) in struct_def.fields().iter().enumerate() {
+                        let name = field.ident.map(|ident| ident.name)
+                            .unwrap_or(token::intern(&index.to_string()));
+                        this.create_def(field.id, DefPathData::Field(name));
                     }
                 }
                 _ => {}
@@ -205,14 +207,10 @@ impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
     }
 
     fn visit_pat(&mut self, pat: &'ast Pat) {
-        let maybe_binding = match pat.node {
-            PatKind::Ident(_, id, _) => Some(id.node),
-            _ => None
-        };
-
         let parent_def = self.parent_def;
-        if let Some(id) = maybe_binding {
-            let def = self.create_def(pat.id, DefPathData::Binding(id.name));
+
+        if let PatKind::Ident(_, id, _) = pat.node {
+            let def = self.create_def(pat.id, DefPathData::Binding(id.node.name));
             self.parent_def = Some(def);
         }
 
@@ -353,14 +351,10 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
     }
 
     fn visit_pat(&mut self, pat: &'ast hir::Pat) {
-        let maybe_binding = match pat.node {
-            hir::PatKind::Ident(_, id, _) => Some(id.node),
-            _ => None
-        };
-
         let parent_def = self.parent_def;
-        if let Some(id) = maybe_binding {
-            let def = self.create_def(pat.id, DefPathData::Binding(id.name));
+
+        if let hir::PatKind::Ident(_, id, _) = pat.node {
+            let def = self.create_def(pat.id, DefPathData::Binding(id.node.name));
             self.parent_def = Some(def);
         }
 
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 1d0c40646b5..92f8c9249c8 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -196,7 +196,7 @@ pub struct Map<'ast> {
     /// plain old integers.
     map: RefCell<Vec<MapEntry<'ast>>>,
 
-    definitions: RefCell<Definitions>,
+    definitions: &'ast RefCell<Definitions>,
 }
 
 impl<'ast> Map<'ast> {
@@ -789,7 +789,9 @@ pub fn collect_definitions<'ast>(krate: &'ast ast::Crate) -> Definitions {
     def_collector.definitions
 }
 
-pub fn map_crate<'ast>(forest: &'ast mut Forest, definitions: Definitions) -> Map<'ast> {
+pub fn map_crate<'ast>(forest: &'ast mut Forest,
+                       definitions: &'ast RefCell<Definitions>)
+                       -> Map<'ast> {
     let mut collector = NodeCollector::root(&forest.krate);
     intravisit::walk_crate(&mut collector, &forest.krate);
     let map = collector.map;
@@ -814,7 +816,7 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest, definitions: Definitions) -> Ma
         forest: forest,
         dep_graph: forest.dep_graph.clone(),
         map: RefCell::new(map),
-        definitions: RefCell::new(definitions),
+        definitions: definitions,
     }
 }
 
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 6724c0ed8eb..26422e3194a 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -43,6 +43,7 @@ use super::Compilation;
 
 use serialize::json;
 
+use std::cell::RefCell;
 use std::collections::HashMap;
 use std::env;
 use std::ffi::{OsString, OsStr};
@@ -123,9 +124,9 @@ pub fn compile_input(sess: &Session,
         let dep_graph = DepGraph::new(sess.opts.build_dep_graph);
 
         // Collect defintions for def ids.
-        let defs = time(sess.time_passes(),
-                        "collecting defs",
-                        || hir_map::collect_definitions(&expanded_crate));
+        let defs = &RefCell::new(time(sess.time_passes(),
+                                 "collecting defs",
+                                 || hir_map::collect_definitions(&expanded_crate)));
 
         time(sess.time_passes(),
              "external crate/lib resolution",
@@ -133,7 +134,7 @@ pub fn compile_input(sess: &Session,
                     .read_crates(&dep_graph));
 
         // Lower ast -> hir.
-        let lcx = LoweringContext::new(sess, Some(&expanded_crate));
+        let lcx = LoweringContext::new(sess, Some(&expanded_crate), defs);
         let hir_forest = &mut time(sess.time_passes(),
                                    "lowering ast -> hir",
                                    || hir_map::Forest::new(lower_crate(&lcx, &expanded_crate),
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 769449b96d2..0e100f48ac3 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -199,14 +199,9 @@ pub fn run_compiler<'a>(args: &[String],
     // It is somewhat unfortunate that this is hardwired in - this is forced by
     // the fact that pretty_print_input requires the session by value.
     let pretty = callbacks.parse_pretty(&sess, &matches);
-    match pretty {
-        Some((ppm, opt_uii)) => {
-            pretty::pretty_print_input(sess, &cstore, cfg, &input, ppm, opt_uii, ofile);
-            return (Ok(()), None);
-        }
-        None => {
-            // continue
-        }
+    if let Some((ppm, opt_uii)) = pretty {
+        pretty::pretty_print_input(sess, &cstore, cfg, &input, ppm, opt_uii, ofile);
+        return (Ok(()), None);
     }
 
     let plugins = sess.opts.debugging_opts.extra_plugins.clone();
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 2e3a477e048..b1143fd3e84 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -29,6 +29,7 @@ use rustc_borrowck as borrowck;
 use rustc_borrowck::graphviz as borrowck_dot;
 use rustc_resolve as resolve;
 use rustc_metadata::cstore::CStore;
+use rustc_metadata::creader::LocalCrateReader;
 
 use rustc_mir::pretty::write_mir_pretty;
 use rustc_mir::graphviz::write_mir_graphviz;
@@ -43,6 +44,7 @@ use syntax::util::small_vector::SmallVector;
 
 use graphviz as dot;
 
+use std::cell::RefCell;
 use std::fs::File;
 use std::io::{self, Write};
 use std::iter;
@@ -719,7 +721,7 @@ pub fn pretty_print_input(sess: Session,
     let is_expanded = needs_expansion(&ppm);
     let compute_ast_map = needs_ast_map(&ppm, &opt_uii);
     let krate = if compute_ast_map {
-        match driver::phase_2_configure_and_expand(&sess, &cstore, krate, &id[..], None) {
+        match driver::phase_2_configure_and_expand(&sess, &cstore, krate, &id, None) {
             Err(_) => return,
             Ok(k) => driver::assign_node_ids(&sess, k),
         }
@@ -730,15 +732,18 @@ pub fn pretty_print_input(sess: Session,
     // There is some twisted, god-forsaken tangle of lifetimes here which makes
     // the ordering of stuff super-finicky.
     let mut hir_forest;
-    let lcx = LoweringContext::new(&sess, Some(&krate));
-    let arenas = ty::CtxtArenas::new();
+    let mut _defs = None;
     let dep_graph = DepGraph::new(false);
+    let arenas = ty::CtxtArenas::new();
     let _ignore = dep_graph.in_ignore();
     let ast_map = if compute_ast_map {
-        let defs = hir_map::collect_definitions(&krate);
+        _defs = Some(RefCell::new(hir_map::collect_definitions(&krate)));
+        let defs = _defs.as_ref().unwrap();
+        LocalCrateReader::new(&sess, &cstore, defs, &krate, &id).read_crates(&dep_graph);
+        let lcx = LoweringContext::new(&sess, Some(&krate), defs);
+
         hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate), dep_graph.clone());
-        let map = hir_map::map_crate(&mut hir_forest, defs);
-        Some(map)
+        Some(hir_map::map_crate(&mut hir_forest, defs))
     } else {
         None
     };
@@ -751,7 +756,7 @@ pub fn pretty_print_input(sess: Session,
                   .unwrap()
                   .as_bytes()
                   .to_vec();
-    let mut rdr = &src[..];
+    let mut rdr = &*src;
 
     let mut out = Vec::new();
 
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index fc12d546288..ce92dd158c9 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -27,8 +27,10 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::relate::TypeRelation;
 use rustc::infer::{self, InferOk, InferResult, TypeOrigin};
 use rustc_metadata::cstore::CStore;
+use rustc_metadata::creader::LocalCrateReader;
 use rustc::hir::map as hir_map;
 use rustc::session::{self, config};
+use std::cell::RefCell;
 use std::rc::Rc;
 use syntax::ast;
 use syntax::abi::Abi;
@@ -119,13 +121,15 @@ fn test_env<F>(source_string: &str,
     let krate = driver::phase_2_configure_and_expand(&sess, &cstore, krate, "test", None)
                     .expect("phase 2 aborted");
 
-    let krate = driver::assign_node_ids(&sess, krate);
-    let lcx = LoweringContext::new(&sess, Some(&krate));
     let dep_graph = DepGraph::new(false);
+    let krate = driver::assign_node_ids(&sess, krate);
+    let defs = &RefCell::new(hir_map::collect_definitions(&krate));
+    LocalCrateReader::new(&sess, &cstore, defs, &krate, "test_crate").read_crates(&dep_graph);
+    let lcx = LoweringContext::new(&sess, Some(&krate), defs);
     let _ignore = dep_graph.in_ignore();
-    let mut hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate), dep_graph.clone());
+    let mut hir_forest = &mut hir_map::Forest::new(lower_crate(&lcx, &krate), dep_graph.clone());
     let arenas = ty::CtxtArenas::new();
-    let ast_map = driver::make_map(&sess, &mut hir_forest);
+    let ast_map = hir_map::map_crate(hir_forest, defs);
 
     // run just enough stuff to build a tcx:
     let lang_items = lang_items::collect_language_items(&sess, &ast_map);
diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs
index 49512a5018e..2d6a043e34a 100644
--- a/src/librustc_metadata/astencode.rs
+++ b/src/librustc_metadata/astencode.rs
@@ -1339,7 +1339,7 @@ fn roundtrip(in_item: hir::Item) {
 fn test_basic() {
     let cx = mk_ctxt();
     let fnia = FakeNodeIdAssigner;
-    let lcx = LoweringContext::new(&fnia, None);
+    let lcx = LoweringContext::testing_context(&fnia);
     roundtrip(lower_item(&lcx, &quote_item!(&cx,
         fn foo() {}
     ).unwrap()));
@@ -1349,7 +1349,7 @@ fn test_basic() {
 fn test_smalltalk() {
     let cx = mk_ctxt();
     let fnia = FakeNodeIdAssigner;
-    let lcx = LoweringContext::new(&fnia, None);
+    let lcx = LoweringContext::testing_context(&fnia);
     roundtrip(lower_item(&lcx, &quote_item!(&cx,
         fn foo() -> isize { 3 + 4 } // first smalltalk program ever executed.
     ).unwrap()));
@@ -1359,7 +1359,7 @@ fn test_smalltalk() {
 fn test_more() {
     let cx = mk_ctxt();
     let fnia = FakeNodeIdAssigner;
-    let lcx = LoweringContext::new(&fnia, None);
+    let lcx = LoweringContext::testing_context(&fnia);
     roundtrip(lower_item(&lcx, &quote_item!(&cx,
         fn foo(x: usize, y: usize) -> usize {
             let z = x + y;
@@ -1378,7 +1378,7 @@ fn test_simplification() {
         }
     ).unwrap();
     let fnia = FakeNodeIdAssigner;
-    let lcx = LoweringContext::new(&fnia, None);
+    let lcx = LoweringContext::testing_context(&fnia);
     let hir_item = lower_item(&lcx, &item);
     let item_in = InlinedItemRef::Item(&hir_item);
     let item_out = simplify_ast(item_in);
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 4ba59a3d7eb..635ef4ab358 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -45,7 +45,7 @@ pub struct LocalCrateReader<'a> {
     cstore: &'a CStore,
     creader: CrateReader<'a>,
     krate: &'a ast::Crate,
-    defintions: &'a hir_map::Definitions,
+    defintions: &'a RefCell<hir_map::Definitions>,
 }
 
 pub struct CrateReader<'a> {
@@ -59,6 +59,7 @@ pub struct CrateReader<'a> {
 impl<'a, 'ast> visit::Visitor<'ast> for LocalCrateReader<'a> {
     fn visit_item(&mut self, a: &'ast ast::Item) {
         self.process_item(a);
+        visit::walk_item(self, a);
     }
 }
 
@@ -81,6 +82,7 @@ fn should_link(i: &ast::Item) -> bool {
     !attr::contains_name(&i.attrs, "no_link")
 }
 
+#[derive(Debug)]
 struct CrateInfo {
     ident: String,
     name: String,
@@ -750,7 +752,7 @@ impl<'a> CrateReader<'a> {
 impl<'a> LocalCrateReader<'a> {
     pub fn new(sess: &'a Session,
                cstore: &'a CStore,
-               defs: &'a hir_map::Definitions,
+               defs: &'a RefCell<hir_map::Definitions>,
                krate: &'a ast::Crate,
                local_crate_name: &str)
                -> LocalCrateReader<'a> {
@@ -807,9 +809,10 @@ impl<'a> LocalCrateReader<'a> {
                                                                       i.span,
                                                                       PathKind::Crate,
                                                                       true);
-                        let def_id = self.defintions.opt_local_def_id(i.id).unwrap();
 
-                        let len = self.defintions.def_path(def_id.index).data.len();
+                        let defs = self.defintions.borrow();
+                        let def_id = defs.opt_local_def_id(i.id).unwrap();
+                        let len = defs.def_path(def_id.index).data.len();
 
                         self.creader.update_extern_crate(cnum,
                                                          ExternCrate {
diff --git a/src/librustc_save_analysis/csv_dumper.rs b/src/librustc_save_analysis/csv_dumper.rs
index 0e02830db7a..45ec9a97a11 100644
--- a/src/librustc_save_analysis/csv_dumper.rs
+++ b/src/librustc_save_analysis/csv_dumper.rs
@@ -17,10 +17,10 @@ use super::data::*;
 use super::dump::Dump;
 use super::span_utils::SpanUtils;
 
-pub struct CsvDumper<'a, 'b, W: 'b> {
+pub struct CsvDumper<'tcx, 'b, W: 'b> {
     output: &'b mut W,
     dump_spans: bool,
-    span: SpanUtils<'a>
+    span: SpanUtils<'tcx>
 }
 
 impl<'a, 'b, W: Write> CsvDumper<'a, 'b, W> {
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 3784c95fe2b..bf6ad703963 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -42,7 +42,7 @@ use syntax::visit::{self, Visitor};
 use syntax::print::pprust::{path_to_string, ty_to_string};
 use syntax::ptr::P;
 
-use rustc::hir::lowering::{lower_expr, LoweringContext};
+use rustc::hir::lowering::lower_expr;
 
 use super::{escape, generated_code, SaveContext, PathCollector};
 use super::data::*;
@@ -60,12 +60,12 @@ macro_rules! down_cast_data {
     };
 }
 
-pub struct DumpVisitor<'l, 'tcx: 'l, D: 'l> {
+pub struct DumpVisitor<'l, 'tcx: 'l, 'll, D: 'll> {
     save_ctxt: SaveContext<'l, 'tcx>,
     sess: &'l Session,
     tcx: &'l TyCtxt<'tcx>,
     analysis: &'l ty::CrateAnalysis<'l>,
-    dumper: &'l mut D,
+    dumper: &'ll mut D,
 
     span: SpanUtils<'l>,
 
@@ -77,22 +77,19 @@ pub struct DumpVisitor<'l, 'tcx: 'l, D: 'l> {
     // one macro use per unique callsite span.
     mac_defs: HashSet<Span>,
     mac_uses: HashSet<Span>,
-
 }
 
-impl <'l, 'tcx, D> DumpVisitor<'l, 'tcx, D>
-where D: Dump
-{
+impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
     pub fn new(tcx: &'l TyCtxt<'tcx>,
-               lcx: &'l LoweringContext<'l>,
+               save_ctxt: SaveContext<'l, 'tcx>,
                analysis: &'l ty::CrateAnalysis<'l>,
-               dumper: &'l mut D)
-               -> DumpVisitor<'l, 'tcx, D> {
+               dumper: &'ll mut D)
+               -> DumpVisitor<'l, 'tcx, 'll, D> {
         let span_utils = SpanUtils::new(&tcx.sess);
         DumpVisitor {
             sess: &tcx.sess,
             tcx: tcx,
-            save_ctxt: SaveContext::from_span_utils(tcx, lcx, span_utils.clone()),
+            save_ctxt: save_ctxt,
             analysis: analysis,
             dumper: dumper,
             span: span_utils.clone(),
@@ -103,7 +100,7 @@ where D: Dump
     }
 
     fn nest<F>(&mut self, scope_id: NodeId, f: F)
-        where F: FnOnce(&mut DumpVisitor<'l, 'tcx, D>)
+        where F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, D>)
     {
         let parent_scope = self.cur_scope;
         self.cur_scope = scope_id;
@@ -982,7 +979,7 @@ where D: Dump
     }
 }
 
-impl<'l, 'tcx, 'v, D: Dump + 'l> Visitor<'v> for DumpVisitor<'l, 'tcx, D> {
+impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx, 'll, D> {
     fn visit_item(&mut self, item: &ast::Item) {
         use syntax::ast::ItemKind::*;
         self.process_macro_use(item.span, item.id);
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 4596398c315..9148b53322b 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -73,7 +73,7 @@ pub mod recorder {
 pub struct SaveContext<'l, 'tcx: 'l> {
     tcx: &'l TyCtxt<'tcx>,
     lcx: &'l lowering::LoweringContext<'l>,
-    span_utils: SpanUtils<'l>,
+    span_utils: SpanUtils<'tcx>,
 }
 
 macro_rules! option_try(
@@ -90,7 +90,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
 
     pub fn from_span_utils(tcx: &'l TyCtxt<'tcx>,
                            lcx: &'l lowering::LoweringContext<'l>,
-                           span_utils: SpanUtils<'l>)
+                           span_utils: SpanUtils<'tcx>)
                            -> SaveContext<'l, 'tcx> {
         SaveContext {
             tcx: tcx,
@@ -680,7 +680,7 @@ impl<'v> Visitor<'v> for PathCollector {
 pub fn process_crate<'l, 'tcx>(tcx: &'l TyCtxt<'tcx>,
                                lcx: &'l lowering::LoweringContext<'l>,
                                krate: &ast::Crate,
-                               analysis: &ty::CrateAnalysis,
+                               analysis: &'l ty::CrateAnalysis<'l>,
                                cratename: &str,
                                odir: Option<&Path>) {
     let _ignore = tcx.dep_graph.in_ignore();
@@ -726,9 +726,10 @@ pub fn process_crate<'l, 'tcx>(tcx: &'l TyCtxt<'tcx>,
     });
     root_path.pop();
 
-    let utils = SpanUtils::new(&tcx.sess);
+    let utils: SpanUtils<'tcx> = SpanUtils::new(&tcx.sess);
+    let save_ctxt = SaveContext::new(tcx, lcx);
     let mut dumper = CsvDumper::new(&mut output_file, utils);
-    let mut visitor = DumpVisitor::new(tcx, lcx, analysis, &mut dumper);
+    let mut visitor = DumpVisitor::new(tcx, save_ctxt, analysis, &mut dumper);
     // FIXME: we don't write anything!
 
     visitor.dump_crate_info(cratename, krate);
diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs
index f410d428177..c64eeb92737 100644
--- a/src/librustc_save_analysis/span_utils.rs
+++ b/src/librustc_save_analysis/span_utils.rs
@@ -26,6 +26,8 @@ use syntax::parse::token::{keywords, Token};
 #[derive(Clone)]
 pub struct SpanUtils<'a> {
     pub sess: &'a Session,
+    // FIXME given that we clone SpanUtils all over the place, this err_count is
+    // probably useless and any logic relying on it is bogus.
     pub err_count: Cell<isize>,
 }
 
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index b7c60b8a524..6d1e91a687e 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -22,6 +22,7 @@ use rustc_trans::back::link;
 use rustc_resolve as resolve;
 use rustc::hir::lowering::{lower_crate, LoweringContext};
 use rustc_metadata::cstore::CStore;
+use rustc_metadata::creader::LocalCrateReader;
 
 use syntax::{ast, codemap, errors};
 use syntax::errors::emitter::ColorConfig;
@@ -151,14 +152,18 @@ pub fn run_core(search_paths: SearchPaths,
                     .expect("phase_2_configure_and_expand aborted in rustdoc!");
 
     let krate = driver::assign_node_ids(&sess, krate);
+    let dep_graph = DepGraph::new(false);
+
+    let defs = &RefCell::new(hir_map::collect_definitions(&krate));
+    LocalCrateReader::new(&sess, &cstore, &defs, &krate, &name).read_crates(&dep_graph);
+    let lcx = LoweringContext::new(&sess, Some(&krate), defs);
+
     // Lower ast -> hir.
-    let lcx = LoweringContext::new(&sess, Some(&krate));
-    let mut hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate), DepGraph::new(false));
+    let mut hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate), dep_graph);
     let arenas = ty::CtxtArenas::new();
-    let hir_map = driver::make_map(&sess, &mut hir_forest);
+    let hir_map = hir_map::map_crate(&mut hir_forest, defs);
 
     abort_on_err(driver::phase_3_run_analysis_passes(&sess,
-                                                     &cstore,
                                                      hir_map,
                                                      &arenas,
                                                      &name,
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 5a7050fb42f..487aac1806e 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -94,15 +94,17 @@ pub fn run(input: &str,
                                                      "rustdoc-test", None)
         .expect("phase_2_configure_and_expand aborted in rustdoc!");
     let krate = driver::assign_node_ids(&sess, krate);
-    let lcx = LoweringContext::new(&sess, Some(&krate));
+    let dep_graph = DepGraph::new(false);
+    let defs = &RefCell::new(hir_map::collect_definitions(&krate));
+
+    let lcx = LoweringContext::new(&sess, Some(&krate), defs);
     let krate = lower_crate(&lcx, &krate);
 
     let opts = scrape_test_config(&krate);
 
-    let dep_graph = DepGraph::new(false);
     let _ignore = dep_graph.in_ignore();
     let mut forest = hir_map::Forest::new(krate, dep_graph.clone());
-    let map = hir_map::map_crate(&mut forest);
+    let map = hir_map::map_crate(&mut forest, defs);
 
     let ctx = core::DocContext {
         map: &map,
diff --git a/src/test/run-make/execution-engine/test.rs b/src/test/run-make/execution-engine/test.rs
index 12cc475f121..86b9c4c81c6 100644
--- a/src/test/run-make/execution-engine/test.rs
+++ b/src/test/run-make/execution-engine/test.rs
@@ -20,6 +20,7 @@ extern crate rustc_metadata;
 extern crate rustc_resolve;
 #[macro_use] extern crate syntax;
 
+use std::cell::RefCell;
 use std::ffi::{CStr, CString};
 use std::mem::transmute;
 use std::path::PathBuf;
@@ -35,6 +36,7 @@ use rustc::session::build_session;
 use rustc_driver::{driver, abort_on_err};
 use rustc::hir::lowering::{lower_crate, LoweringContext};
 use rustc_resolve::MakeGlobMap;
+use rustc_metadata::creader::LocalCrateReader;
 use rustc_metadata::cstore::CStore;
 use libc::c_void;
 
@@ -237,15 +239,17 @@ fn compile_program(input: &str, sysroot: PathBuf)
         let krate = driver::phase_2_configure_and_expand(&sess, &cstore, krate, &id, None)
             .expect("phase_2 returned `None`");
 
+        let dep_graph = DepGraph::new(sess.opts.build_dep_graph);
         let krate = driver::assign_node_ids(&sess, krate);
-        let lcx = LoweringContext::new(&sess, Some(&krate));
-        let dep_graph = DepGraph::new(sess.opts.build_dep_graph());
+        let defs = RefCell::new(ast_map::collect_definitions(&krate));
+        LocalCrateReader::new(&sess, &cstore, &defs, &krate, &id).read_crates(&dep_graph);
+        let lcx = LoweringContext::new(&sess, Some(&krate), &defs);
         let mut hir_forest = ast_map::Forest::new(lower_crate(&lcx, &krate), dep_graph);
         let arenas = ty::CtxtArenas::new();
-        let ast_map = driver::make_map(&sess, &mut hir_forest);
+        let ast_map = ast_map::map_crate(&mut hir_forest, &defs);
 
         abort_on_err(driver::phase_3_run_analysis_passes(
-            &sess, &cstore, ast_map, &arenas, &id,
+            &sess, ast_map, &arenas, &id,
             MakeGlobMap::No, |tcx, mir_map, analysis, _| {
 
             let trans = driver::phase_4_translate_to_llvm(tcx, mir_map.unwrap(), analysis);

From 0be3c8c56977c1f0d875461279e00bca7b4e5ebf Mon Sep 17 00:00:00 2001
From: Nick Cameron <ncameron@mozilla.com>
Date: Tue, 19 Apr 2016 16:16:40 +1200
Subject: [PATCH 9/9] rebasing

---
 src/librustc/hir/map/def_collector.rs      | 4 ++--
 src/librustc_driver/driver.rs              | 2 +-
 src/test/run-make/execution-engine/test.rs | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index b2456f4ab87..053d32305be 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -109,9 +109,9 @@ impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
             ItemKind::DefaultImpl(..) | ItemKind::Impl(..) =>
                 DefPathData::Impl,
             ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Trait(..) |
-            ItemKind::ExternCrate(..) | ItemKind::Mod(..) | ItemKind::ForeignMod(..) |
-            ItemKind::Ty(..) =>
+            ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
                 DefPathData::TypeNs(i.ident.name),
+            ItemKind::Mod(..) => DefPathData::Module(i.ident.name),
             ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
                 DefPathData::ValueNs(i.ident.name),
             ItemKind::Mac(..) => DefPathData::MacroDef(i.ident.name),
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 26422e3194a..5fc2a955c06 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -121,7 +121,7 @@ pub fn compile_input(sess: &Session,
                                 Ok(()));
 
         let expanded_crate = assign_node_ids(sess, expanded_crate);
-        let dep_graph = DepGraph::new(sess.opts.build_dep_graph);
+        let dep_graph = DepGraph::new(sess.opts.build_dep_graph());
 
         // Collect defintions for def ids.
         let defs = &RefCell::new(time(sess.time_passes(),
diff --git a/src/test/run-make/execution-engine/test.rs b/src/test/run-make/execution-engine/test.rs
index 86b9c4c81c6..b9a45c09626 100644
--- a/src/test/run-make/execution-engine/test.rs
+++ b/src/test/run-make/execution-engine/test.rs
@@ -239,7 +239,7 @@ fn compile_program(input: &str, sysroot: PathBuf)
         let krate = driver::phase_2_configure_and_expand(&sess, &cstore, krate, &id, None)
             .expect("phase_2 returned `None`");
 
-        let dep_graph = DepGraph::new(sess.opts.build_dep_graph);
+        let dep_graph = DepGraph::new(sess.opts.build_dep_graph());
         let krate = driver::assign_node_ids(&sess, krate);
         let defs = RefCell::new(ast_map::collect_definitions(&krate));
         LocalCrateReader::new(&sess, &cstore, &defs, &krate, &id).read_crates(&dep_graph);