about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo.net>2017-05-31 16:42:52 +0200
committerMichael Woerister <michaelwoerister@posteo.net>2017-05-31 16:42:52 +0200
commit0cbb8b58e8a5573190c93c9c94e0b003b1cfc6ef (patch)
tree7e915a67a07e0b9d12e4a18218b6f7dcdef41c80
parent9da83a8daf159ef1e85da1a018b5204e47e77e6d (diff)
incr.comp.: Use DefPathHash-based DepNodes in the serialized DepGraph and remove obsolete DefIdDirectory.
-rw-r--r--src/librustc_incremental/persist/data.rs13
-rw-r--r--src/librustc_incremental/persist/directory.rs204
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs12
-rw-r--r--src/librustc_incremental/persist/load.rs77
-rw-r--r--src/librustc_incremental/persist/mod.rs1
-rw-r--r--src/librustc_incremental/persist/save.rs35
6 files changed, 74 insertions, 268 deletions
diff --git a/src/librustc_incremental/persist/data.rs b/src/librustc_incremental/persist/data.rs
index b016ff34bc5..336197d7d6d 100644
--- a/src/librustc_incremental/persist/data.rs
+++ b/src/librustc_incremental/persist/data.rs
@@ -12,13 +12,12 @@
 
 use rustc::dep_graph::{DepNode, WorkProduct, WorkProductId};
 use rustc::hir::def_id::DefIndex;
+use rustc::hir::map::DefPathHash;
 use rustc::ich::Fingerprint;
 use rustc::middle::cstore::EncodedMetadataHash;
 use std::sync::Arc;
 use rustc_data_structures::fx::FxHashMap;
 
-use super::directory::DefPathIndex;
-
 /// Data for use when recompiling the **current crate**.
 #[derive(Debug, RustcEncodable, RustcDecodable)]
 pub struct SerializedDepGraph {
@@ -27,7 +26,7 @@ pub struct SerializedDepGraph {
     /// These are output nodes that have no incoming edges. We track
     /// these separately so that when we reload all edges, we don't
     /// lose track of these nodes.
-    pub bootstrap_outputs: Vec<DepNode<DefPathIndex>>,
+    pub bootstrap_outputs: Vec<DepNode<DefPathHash>>,
 
     /// These are hashes of two things:
     /// - the HIR nodes in this crate
@@ -55,14 +54,14 @@ pub struct SerializedDepGraph {
 /// outgoing edges from a single source together.
 #[derive(Debug, RustcEncodable, RustcDecodable)]
 pub struct SerializedEdgeSet {
-    pub source: DepNode<DefPathIndex>,
-    pub targets: Vec<DepNode<DefPathIndex>>
+    pub source: DepNode<DefPathHash>,
+    pub targets: Vec<DepNode<DefPathHash>>
 }
 
 #[derive(Debug, RustcEncodable, RustcDecodable)]
 pub struct SerializedHash {
     /// def-id of thing being hashed
-    pub dep_node: DepNode<DefPathIndex>,
+    pub dep_node: DepNode<DefPathHash>,
 
     /// the hash as of previous compilation, computed by code in
     /// `hash` module
@@ -115,5 +114,5 @@ pub struct SerializedMetadataHashes {
     /// is only populated if -Z query-dep-graph is specified. It will be
     /// empty otherwise. Importing crates are perfectly happy with just having
     /// the DefIndex.
-    pub index_map: FxHashMap<DefIndex, DefPathIndex>
+    pub index_map: FxHashMap<DefIndex, DefPathHash>
 }
diff --git a/src/librustc_incremental/persist/directory.rs b/src/librustc_incremental/persist/directory.rs
deleted file mode 100644
index b9b86022296..00000000000
--- a/src/librustc_incremental/persist/directory.rs
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright 2014 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.
-
-//! Code to convert a DefId into a DefPath (when serializing) and then
-//! back again (when deserializing). Note that the new DefId
-//! necessarily will not be the same as the old (and of course the
-//! item might even be removed in the meantime).
-
-use rustc::dep_graph::DepNode;
-use rustc::hir::map::DefPath;
-use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use rustc::ty::TyCtxt;
-use rustc::util::nodemap::DefIdMap;
-use std::fmt::{self, Debug};
-use std::iter::once;
-use std::collections::HashMap;
-
-/// Index into the DefIdDirectory
-#[derive(Copy, Clone, Debug, PartialOrd, Ord, Hash, PartialEq, Eq,
-         RustcEncodable, RustcDecodable)]
-pub struct DefPathIndex {
-    index: u32
-}
-
-#[derive(RustcEncodable, RustcDecodable)]
-pub struct DefIdDirectory {
-    // N.B. don't use Removable here because these def-ids are loaded
-    // directly without remapping, so loading them should not fail.
-    paths: Vec<DefPath>,
-
-    // For each crate, saves the crate-name/disambiguator so that
-    // later we can match crate-numbers up again.
-    krates: Vec<CrateInfo>,
-}
-
-#[derive(Debug, RustcEncodable, RustcDecodable)]
-pub struct CrateInfo {
-    krate: CrateNum,
-    name: String,
-    disambiguator: String,
-}
-
-impl DefIdDirectory {
-    pub fn new(krates: Vec<CrateInfo>) -> DefIdDirectory {
-        DefIdDirectory { paths: vec![], krates: krates }
-    }
-
-    fn max_current_crate(&self, tcx: TyCtxt) -> CrateNum {
-        tcx.sess.cstore.crates()
-                       .into_iter()
-                       .max()
-                       .unwrap_or(LOCAL_CRATE)
-    }
-
-    /// Returns a string form for `index`; useful for debugging
-    pub fn def_path_string(&self, tcx: TyCtxt, index: DefPathIndex) -> String {
-        let path = &self.paths[index.index as usize];
-        if self.krate_still_valid(tcx, self.max_current_crate(tcx), path.krate) {
-            path.to_string(tcx)
-        } else {
-            format!("<crate {} changed>", path.krate)
-        }
-    }
-
-    pub fn krate_still_valid(&self,
-                             tcx: TyCtxt,
-                             max_current_crate: CrateNum,
-                             krate: CrateNum) -> bool {
-        // Check that the crate-number still matches. For now, if it
-        // doesn't, just return None. We could do better, such as
-        // finding the new number.
-
-        if krate > max_current_crate {
-            false
-        } else {
-            let old_info = &self.krates[krate.as_usize()];
-            assert_eq!(old_info.krate, krate);
-            let old_name: &str = &old_info.name;
-            let old_disambiguator: &str = &old_info.disambiguator;
-            let new_name: &str = &tcx.crate_name(krate).as_str();
-            let new_disambiguator: &str = &tcx.crate_disambiguator(krate).as_str();
-            old_name == new_name && old_disambiguator == new_disambiguator
-        }
-    }
-
-    pub fn retrace(&self, tcx: TyCtxt) -> RetracedDefIdDirectory {
-
-        fn make_key(name: &str, disambiguator: &str) -> String {
-            format!("{}/{}", name, disambiguator)
-        }
-
-        let new_krates: HashMap<_, _> =
-            once(LOCAL_CRATE)
-            .chain(tcx.sess.cstore.crates())
-            .map(|krate| (make_key(&tcx.crate_name(krate).as_str(),
-                                   &tcx.crate_disambiguator(krate).as_str()), krate))
-            .collect();
-
-        let ids = self.paths.iter()
-                            .map(|path| {
-                                let old_krate_id = path.krate.as_usize();
-                                assert!(old_krate_id < self.krates.len());
-                                let old_crate_info = &self.krates[old_krate_id];
-                                let old_crate_key = make_key(&old_crate_info.name,
-                                                         &old_crate_info.disambiguator);
-                                if let Some(&new_crate_key) = new_krates.get(&old_crate_key) {
-                                    tcx.retrace_path(new_crate_key, &path.data)
-                                } else {
-                                    debug!("crate {:?} no longer exists", old_crate_key);
-                                    None
-                                }
-                            })
-                            .collect();
-        RetracedDefIdDirectory { ids: ids }
-    }
-}
-
-#[derive(Debug, RustcEncodable, RustcDecodable)]
-pub struct RetracedDefIdDirectory {
-    ids: Vec<Option<DefId>>
-}
-
-impl RetracedDefIdDirectory {
-    pub fn def_id(&self, index: DefPathIndex) -> Option<DefId> {
-        self.ids[index.index as usize]
-    }
-
-    pub fn map(&self, node: &DepNode<DefPathIndex>) -> Option<DepNode<DefId>> {
-        node.map_def(|&index| self.def_id(index))
-    }
-}
-
-pub struct DefIdDirectoryBuilder<'a,'tcx:'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    hash: DefIdMap<DefPathIndex>,
-    directory: DefIdDirectory,
-}
-
-impl<'a,'tcx> DefIdDirectoryBuilder<'a,'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> DefIdDirectoryBuilder<'a, 'tcx> {
-        let mut krates: Vec<_> =
-            once(LOCAL_CRATE)
-            .chain(tcx.sess.cstore.crates())
-            .map(|krate| {
-                CrateInfo {
-                    krate: krate,
-                    name: tcx.crate_name(krate).to_string(),
-                    disambiguator: tcx.crate_disambiguator(krate).to_string()
-                }
-            })
-            .collect();
-
-        // the result of crates() is not in order, so sort list of
-        // crates so that we can just index it later
-        krates.sort_by_key(|k| k.krate);
-
-        DefIdDirectoryBuilder {
-            tcx: tcx,
-            hash: DefIdMap(),
-            directory: DefIdDirectory::new(krates),
-        }
-    }
-
-    pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
-        self.tcx
-    }
-
-    pub fn add(&mut self, def_id: DefId) -> DefPathIndex {
-        debug!("DefIdDirectoryBuilder: def_id={:?}", def_id);
-        let tcx = self.tcx;
-        let paths = &mut self.directory.paths;
-        self.hash.entry(def_id)
-                 .or_insert_with(|| {
-                     let def_path = tcx.def_path(def_id);
-                     let index = paths.len() as u32;
-                     paths.push(def_path);
-                     DefPathIndex { index: index }
-                 })
-                 .clone()
-    }
-
-    pub fn map(&mut self, node: &DepNode<DefId>) -> DepNode<DefPathIndex> {
-        node.map_def(|&def_id| Some(self.add(def_id))).unwrap()
-    }
-
-    pub fn directory(&self) -> &DefIdDirectory {
-        &self.directory
-    }
-}
-
-impl Debug for DefIdDirectory {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-        fmt.debug_list()
-           .entries(self.paths.iter().enumerate())
-           .finish()
-    }
-}
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 5facfe36efd..3a428bd7b8f 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -40,7 +40,6 @@
 //! previous revision to compare things to.
 //!
 
-use super::directory::RetracedDefIdDirectory;
 use super::load::DirtyNodes;
 use rustc::dep_graph::{DepGraphQuery, DepNode};
 use rustc::hir;
@@ -58,18 +57,23 @@ const LABEL: &'static str = "label";
 const CFG: &'static str = "cfg";
 
 pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                               dirty_inputs: &DirtyNodes,
-                                               retraced: &RetracedDefIdDirectory) {
+                                               dirty_inputs: &DirtyNodes) {
     // can't add `#[rustc_dirty]` etc without opting in to this feature
     if !tcx.sess.features.borrow().rustc_attrs {
         return;
     }
 
     let _ignore = tcx.dep_graph.in_ignore();
+    let def_path_hash_to_def_id = tcx.def_path_hash_to_def_id.as_ref().unwrap();
     let dirty_inputs: FxHashSet<DepNode<DefId>> =
         dirty_inputs.keys()
-                    .filter_map(|d| retraced.map(d))
+                    .filter_map(|dep_node| {
+                        dep_node.map_def(|def_path_hash| {
+                            def_path_hash_to_def_id.get(def_path_hash).cloned()
+                        })
+                    })
                     .collect();
+
     let query = tcx.dep_graph.query();
     debug!("query-nodes: {:?}", query.nodes());
     let krate = tcx.hir.krate();
diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs
index 7fad600d105..d383f80d5c2 100644
--- a/src/librustc_incremental/persist/load.rs
+++ b/src/librustc_incremental/persist/load.rs
@@ -12,6 +12,7 @@
 
 use rustc::dep_graph::{DepNode, WorkProductId};
 use rustc::hir::def_id::DefId;
+use rustc::hir::map::DefPathHash;
 use rustc::hir::svh::Svh;
 use rustc::ich::Fingerprint;
 use rustc::session::Session;
@@ -24,7 +25,6 @@ use std::sync::Arc;
 
 use IncrementalHashesMap;
 use super::data::*;
-use super::directory::*;
 use super::dirty_clean;
 use super::hash::*;
 use super::fs::*;
@@ -33,7 +33,7 @@ use super::work_product;
 
 // The key is a dirty node. The value is **some** base-input that we
 // can blame it on.
-pub type DirtyNodes = FxHashMap<DepNode<DefPathIndex>, DepNode<DefPathIndex>>;
+pub type DirtyNodes = FxHashMap<DepNode<DefPathHash>, DepNode<DefPathHash>>;
 
 /// If we are in incremental mode, and a previous dep-graph exists,
 /// then load up those nodes/edges that are still valid into the
@@ -118,6 +118,16 @@ fn load_data(sess: &Session, path: &Path) -> Option<Vec<u8>> {
     None
 }
 
+/// Try to convert a DepNode from the old dep-graph into a DepNode in the
+/// current graph by mapping the DefPathHash to a valid DefId. This will fail
+/// if the DefPathHash refers to something that has been removed (because
+/// there is no DefId for that thing anymore).
+fn retrace(tcx: TyCtxt, dep_node: &DepNode<DefPathHash>) -> Option<DepNode<DefId>> {
+    dep_node.map_def(|def_path_hash| {
+        tcx.def_path_hash_to_def_id.as_ref().unwrap().get(def_path_hash).cloned()
+    })
+}
+
 /// Decode the dep graph and load the edges/nodes that are still clean
 /// into `tcx.dep_graph`.
 pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -149,7 +159,6 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         return Ok(());
     }
 
-    let directory = DefIdDirectory::decode(&mut dep_graph_decoder)?;
     let serialized_dep_graph = SerializedDepGraph::decode(&mut dep_graph_decoder)?;
 
     let edge_map: FxHashMap<_, _> = serialized_dep_graph.edges
@@ -157,9 +166,6 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                         .map(|s| (s.source, s.targets))
                                                         .collect();
 
-    // Retrace the paths in the directory to find their current location (if any).
-    let retraced = directory.retrace(tcx);
-
     // Compute the set of nodes from the old graph where some input
     // has changed or been removed. These are "raw" source nodes,
     // which means that they still use the original `DefPathIndex`
@@ -169,8 +175,7 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // the current compilation).
     let dirty_raw_nodes = initial_dirty_nodes(tcx,
                                               incremental_hashes_map,
-                                              &serialized_dep_graph.hashes,
-                                              &retraced);
+                                              &serialized_dep_graph.hashes);
     let dirty_raw_nodes = transitive_dirty_nodes(&edge_map, dirty_raw_nodes);
 
     // Recreate the edges in the graph that are still clean.
@@ -179,7 +184,7 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let mut extra_edges = vec![];
     for (source, targets) in &edge_map {
         for target in targets {
-            process_edges(tcx, source, target, &edge_map, &directory, &retraced, &dirty_raw_nodes,
+            process_edges(tcx, source, target, &edge_map, &dirty_raw_nodes,
                           &mut clean_work_products, &mut dirty_work_products, &mut extra_edges);
         }
     }
@@ -187,7 +192,7 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Recreate bootstrap outputs, which are outputs that have no incoming edges (and hence cannot
     // be dirty).
     for bootstrap_output in &serialized_dep_graph.bootstrap_outputs {
-        if let Some(n) = retraced.map(bootstrap_output) {
+        if let Some(n) = retrace(tcx, bootstrap_output) {
             if let DepNode::WorkProduct(ref wp) = n {
                 clean_work_products.insert(wp.clone());
             }
@@ -214,7 +219,7 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // the edge from `Hir(X)` to `Bar` (or, if `Bar` itself cannot be
     // recreated, to the targets of `Bar`).
     while let Some((source, target)) = extra_edges.pop() {
-        process_edges(tcx, source, target, &edge_map, &directory, &retraced, &dirty_raw_nodes,
+        process_edges(tcx, source, target, &edge_map, &dirty_raw_nodes,
                       &mut clean_work_products, &mut dirty_work_products, &mut extra_edges);
     }
 
@@ -222,10 +227,9 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // dirty.
     reconcile_work_products(tcx, work_products, &clean_work_products);
 
-    dirty_clean::check_dirty_clean_annotations(tcx, &dirty_raw_nodes, &retraced);
+    dirty_clean::check_dirty_clean_annotations(tcx, &dirty_raw_nodes);
 
     load_prev_metadata_hashes(tcx,
-                              &retraced,
                               &mut *incremental_hashes_map.prev_metadata_hashes.borrow_mut());
     Ok(())
 }
@@ -234,8 +238,7 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 /// a bit vector where the index is the DefPathIndex.
 fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  incremental_hashes_map: &IncrementalHashesMap,
-                                 serialized_hashes: &[SerializedHash],
-                                 retraced: &RetracedDefIdDirectory)
+                                 serialized_hashes: &[SerializedHash])
                                  -> DirtyNodes {
     let mut hcx = HashContext::new(tcx, incremental_hashes_map);
     let mut dirty_nodes = FxHashMap();
@@ -249,7 +252,7 @@ fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     };
 
     for hash in serialized_hashes {
-        if let Some(dep_node) = retraced.map(&hash.dep_node) {
+        if let Some(dep_node) = retrace(tcx, &hash.dep_node) {
             if let Some(current_hash) = hcx.hash(&dep_node) {
                 if current_hash == hash.hash {
                     debug!("initial_dirty_nodes: {:?} is clean (hash={:?})",
@@ -282,11 +285,11 @@ fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     dirty_nodes
 }
 
-fn transitive_dirty_nodes(edge_map: &FxHashMap<DepNode<DefPathIndex>, Vec<DepNode<DefPathIndex>>>,
+fn transitive_dirty_nodes(edge_map: &FxHashMap<DepNode<DefPathHash>, Vec<DepNode<DefPathHash>>>,
                           mut dirty_nodes: DirtyNodes)
                           -> DirtyNodes
 {
-    let mut stack: Vec<(DepNode<DefPathIndex>, DepNode<DefPathIndex>)> = vec![];
+    let mut stack: Vec<(DepNode<DefPathHash>, DepNode<DefPathHash>)> = vec![];
     stack.extend(dirty_nodes.iter().map(|(s, b)| (s.clone(), b.clone())));
     while let Some((source, blame)) = stack.pop() {
         // we know the source is dirty (because of the node `blame`)...
@@ -348,7 +351,6 @@ fn delete_dirty_work_product(tcx: TyCtxt,
 }
 
 fn load_prev_metadata_hashes(tcx: TyCtxt,
-                             retraced: &RetracedDefIdDirectory,
                              output: &mut FxHashMap<DefId, Fingerprint>) {
     if !tcx.sess.opts.debugging_opts.query_dep_graph {
         return
@@ -388,9 +390,11 @@ fn load_prev_metadata_hashes(tcx: TyCtxt,
     debug!("load_prev_metadata_hashes() - Mapping DefIds");
 
     assert_eq!(serialized_hashes.index_map.len(), serialized_hashes.entry_hashes.len());
+    let def_path_hash_to_def_id = tcx.def_path_hash_to_def_id.as_ref().unwrap();
+
     for serialized_hash in serialized_hashes.entry_hashes {
-        let def_path_index = serialized_hashes.index_map[&serialized_hash.def_index];
-        if let Some(def_id) = retraced.def_id(def_path_index) {
+        let def_path_hash = serialized_hashes.index_map[&serialized_hash.def_index];
+        if let Some(&def_id) = def_path_hash_to_def_id.get(&def_path_hash) {
             let old = output.insert(def_id, serialized_hash.hash);
             assert!(old.is_none(), "already have hash for {:?}", def_id);
         }
@@ -402,15 +406,13 @@ fn load_prev_metadata_hashes(tcx: TyCtxt,
 
 fn process_edges<'a, 'tcx, 'edges>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    source: &'edges DepNode<DefPathIndex>,
-    target: &'edges DepNode<DefPathIndex>,
-    edges: &'edges FxHashMap<DepNode<DefPathIndex>, Vec<DepNode<DefPathIndex>>>,
-    directory: &DefIdDirectory,
-    retraced: &RetracedDefIdDirectory,
+    source: &'edges DepNode<DefPathHash>,
+    target: &'edges DepNode<DefPathHash>,
+    edges: &'edges FxHashMap<DepNode<DefPathHash>, Vec<DepNode<DefPathHash>>>,
     dirty_raw_nodes: &DirtyNodes,
     clean_work_products: &mut FxHashSet<Arc<WorkProductId>>,
     dirty_work_products: &mut FxHashSet<Arc<WorkProductId>>,
-    extra_edges: &mut Vec<(&'edges DepNode<DefPathIndex>, &'edges DepNode<DefPathIndex>)>)
+    extra_edges: &mut Vec<(&'edges DepNode<DefPathHash>, &'edges DepNode<DefPathHash>)>)
 {
     // If the target is dirty, skip the edge. If this is an edge
     // that targets a work-product, we can print the blame
@@ -419,14 +421,21 @@ fn process_edges<'a, 'tcx, 'edges>(
         if let DepNode::WorkProduct(ref wp) = *target {
             if tcx.sess.opts.debugging_opts.incremental_info {
                 if dirty_work_products.insert(wp.clone()) {
-                    // It'd be nice to pretty-print these paths better than just
-                    // using the `Debug` impls, but wev.
+                    // Try to reconstruct the human-readable version of the
+                    // DepNode. This cannot be done for things that where
+                    // removed.
+                    let readable_blame = if let Some(dep_node) = retrace(tcx, blame) {
+                        dep_node.map_def(|&def_id| Some(tcx.def_path(def_id).to_string(tcx)))
+                                .unwrap()
+                    } else {
+                        blame.map_def(|def_path_hash| Some(format!("{:?}", def_path_hash)))
+                             .unwrap()
+                    };
+
                     println!("incremental: module {:?} is dirty because {:?} \
                               changed or was removed",
                              wp,
-                             blame.map_def(|&index| {
-                                 Some(directory.def_path_string(tcx, index))
-                             }).unwrap());
+                             readable_blame);
                 }
             }
         }
@@ -439,8 +448,8 @@ fn process_edges<'a, 'tcx, 'edges>(
     // Retrace the source -> target edges to def-ids and then create
     // an edge in the graph. Retracing may yield none if some of the
     // data happens to have been removed.
-    if let Some(source_node) = retraced.map(source) {
-        if let Some(target_node) = retraced.map(target) {
+    if let Some(source_node) = retrace(tcx, source) {
+        if let Some(target_node) = retrace(tcx, target) {
             let _task = tcx.dep_graph.in_task(target_node);
             tcx.dep_graph.read(source_node);
             if let DepNode::WorkProduct(ref wp) = *target {
diff --git a/src/librustc_incremental/persist/mod.rs b/src/librustc_incremental/persist/mod.rs
index 3ae8fcdfb51..c03a0ab4ba2 100644
--- a/src/librustc_incremental/persist/mod.rs
+++ b/src/librustc_incremental/persist/mod.rs
@@ -13,7 +13,6 @@
 //! various HIR nodes.
 
 mod data;
-mod directory;
 mod dirty_clean;
 mod fs;
 mod hash;
diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs
index 06e49e9d37c..28ac5a0fdf5 100644
--- a/src/librustc_incremental/persist/save.rs
+++ b/src/librustc_incremental/persist/save.rs
@@ -24,7 +24,6 @@ use std::path::PathBuf;
 
 use IncrementalHashesMap;
 use super::data::*;
-use super::directory::*;
 use super::hash::*;
 use super::preds::*;
 use super::fs::*;
@@ -43,7 +42,6 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         return;
     }
 
-    let mut builder = DefIdDirectoryBuilder::new(tcx);
     let query = tcx.dep_graph.query();
 
     if tcx.sess.opts.debugging_opts.incremental_info {
@@ -65,14 +63,13 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 |e| encode_metadata_hashes(tcx,
                                            svh,
                                            metadata_hashes,
-                                           &mut builder,
                                            &mut current_metadata_hashes,
                                            e));
     }
 
     save_in(sess,
             dep_graph_path(sess),
-            |e| encode_dep_graph(&preds, &mut builder, e));
+            |e| encode_dep_graph(tcx, &preds, e));
 
     let prev_metadata_hashes = incremental_hashes_map.prev_metadata_hashes.borrow();
     dirty_clean::check_dirty_clean_metadata(tcx,
@@ -167,14 +164,17 @@ fn save_in<F>(sess: &Session, path_buf: PathBuf, encode: F)
     }
 }
 
-pub fn encode_dep_graph(preds: &Predecessors,
-                        builder: &mut DefIdDirectoryBuilder,
+pub fn encode_dep_graph(tcx: TyCtxt,
+                        preds: &Predecessors,
                         encoder: &mut Encoder)
                         -> io::Result<()> {
     // First encode the commandline arguments hash
-    let tcx = builder.tcx();
     tcx.sess.opts.dep_tracking_hash().encode(encoder)?;
 
+    let to_hash_based_node = |dep_node: &DepNode<DefId>| {
+        dep_node.map_def(|&def_id| Some(tcx.def_path_hash(def_id))).unwrap()
+    };
+
     // Create a flat list of (Input, WorkProduct) edges for
     // serialization.
     let mut edges = FxHashMap();
@@ -191,8 +191,8 @@ pub fn encode_dep_graph(preds: &Predecessors,
             _ => (),
         }
         debug!("serialize edge: {:?} -> {:?}", source, target);
-        let source = builder.map(source);
-        let target = builder.map(target);
+        let source = to_hash_based_node(source);
+        let target = to_hash_based_node(target);
         edges.entry(source).or_insert(vec![]).push(target);
     }
 
@@ -203,9 +203,10 @@ pub fn encode_dep_graph(preds: &Predecessors,
     }
 
     // Create the serialized dep-graph.
-    let bootstrap_outputs = preds.bootstrap_outputs.iter()
-                                                   .map(|n| builder.map(n))
-                                                   .collect();
+    let bootstrap_outputs = preds.bootstrap_outputs
+                                 .iter()
+                                 .map(|n| to_hash_based_node(n))
+                                 .collect();
     let edges = edges.into_iter()
                      .map(|(k, v)| SerializedEdgeSet { source: k, targets: v })
                      .collect();
@@ -216,7 +217,7 @@ pub fn encode_dep_graph(preds: &Predecessors,
             .iter()
             .map(|(&dep_node, &hash)| {
                 SerializedHash {
-                    dep_node: builder.map(dep_node),
+                    dep_node: to_hash_based_node(dep_node),
                     hash: hash,
                 }
             })
@@ -231,8 +232,7 @@ pub fn encode_dep_graph(preds: &Predecessors,
 
     debug!("graph = {:#?}", graph);
 
-    // Encode the directory and then the graph data.
-    builder.directory().encode(encoder)?;
+    // Encode the graph data.
     graph.encode(encoder)?;
 
     Ok(())
@@ -241,7 +241,6 @@ pub fn encode_dep_graph(preds: &Predecessors,
 pub fn encode_metadata_hashes(tcx: TyCtxt,
                               svh: Svh,
                               metadata_hashes: &EncodedMetadataHashes,
-                              builder: &mut DefIdDirectoryBuilder,
                               current_metadata_hashes: &mut FxHashMap<DefId, Fingerprint>,
                               encoder: &mut Encoder)
                               -> io::Result<()> {
@@ -256,8 +255,8 @@ pub fn encode_metadata_hashes(tcx: TyCtxt,
             let def_id = DefId::local(serialized_hash.def_index);
 
             // Store entry in the index_map
-            let def_path_index = builder.add(def_id);
-            serialized_hashes.index_map.insert(def_id.index, def_path_index);
+            let def_path_hash = tcx.def_path_hash(def_id);
+            serialized_hashes.index_map.insert(def_id.index, def_path_hash);
 
             // Record hash in current_metadata_hashes
             current_metadata_hashes.insert(def_id, serialized_hash.hash);