about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo.net>2017-06-12 17:00:55 +0200
committerMichael Woerister <michaelwoerister@posteo.net>2017-06-13 12:27:02 +0200
commit5b5499d5e60777b277d97efce5e62ab98c9cf823 (patch)
tree6c1465f541173c7c1e1ea5dc247d7c7c54f57b51
parent3f8b93693da78c2cfe1d7f1dc6834c5ba61e0cc0 (diff)
downloadrust-5b5499d5e60777b277d97efce5e62ab98c9cf823.tar.gz
rust-5b5499d5e60777b277d97efce5e62ab98c9cf823.zip
incr.comp.: Make DepNode's std::fmt::Debug implementation useful again.
-rw-r--r--src/librustc/dep_graph/dep_node.rs124
-rw-r--r--src/librustc/dep_graph/graph.rs19
-rw-r--r--src/librustc/ich/fingerprint.rs11
3 files changed, 150 insertions, 4 deletions
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 3b6a7f87c13..787a9fb38aa 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -67,6 +67,7 @@ use ich::Fingerprint;
 use ty::TyCtxt;
 use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
 use ich::StableHashingContext;
+use std::fmt;
 use std::hash::Hash;
 
 // erase!() just makes tokens go away. It's used to specify which macro argument
@@ -145,7 +146,7 @@ macro_rules! define_dep_nodes {
             ),*
         }
 
-        #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash,
+        #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
                  RustcEncodable, RustcDecodable)]
         pub struct DepNode {
             pub kind: DepKind,
@@ -166,10 +167,22 @@ macro_rules! define_dep_nodes {
                                 let tupled_args = ( $($tuple_arg,)* );
                                 let hash = DepNodeParams::to_fingerprint(&tupled_args,
                                                                          tcx);
-                                return DepNode {
+                                let dep_node = DepNode {
                                     kind: DepKind::$variant,
                                     hash
                                 };
+
+                                if cfg!(debug_assertions) &&
+                                   !dep_node.kind.can_reconstruct_query_key() &&
+                                   (tcx.sess.opts.debugging_opts.incremental_info ||
+                                    tcx.sess.opts.debugging_opts.query_dep_graph)
+                                {
+                                    tcx.dep_graph.register_dep_node_debug_str(dep_node, || {
+                                        tupled_args.to_debug_str(tcx)
+                                    });
+                                }
+
+                                return dep_node;
                             })*
 
                             // struct args
@@ -177,10 +190,22 @@ macro_rules! define_dep_nodes {
                                 let tupled_args = ( $($struct_arg_name,)* );
                                 let hash = DepNodeParams::to_fingerprint(&tupled_args,
                                                                          tcx);
-                                return DepNode {
+                                let dep_node = DepNode {
                                     kind: DepKind::$variant,
                                     hash
                                 };
+
+                                if cfg!(debug_assertions) &&
+                                   !dep_node.kind.can_reconstruct_query_key() &&
+                                   (tcx.sess.opts.debugging_opts.incremental_info ||
+                                    tcx.sess.opts.debugging_opts.query_dep_graph)
+                                {
+                                    tcx.dep_graph.register_dep_node_debug_str(dep_node, || {
+                                        tupled_args.to_debug_str(tcx)
+                                    });
+                                }
+
+                                return dep_node;
                             })*
 
                             DepNode {
@@ -267,6 +292,36 @@ macro_rules! define_dep_nodes {
     );
 }
 
+impl fmt::Debug for DepNode {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{:?}", self.kind)?;
+
+        if !self.kind.has_params() {
+            return Ok(());
+        }
+
+        write!(f, "(")?;
+
+        ::ty::tls::with_opt(|opt_tcx| {
+            if let Some(tcx) = opt_tcx {
+                if let Some(def_id) = self.extract_def_id(tcx) {
+                    write!(f, "{}", tcx.item_path_str(def_id))?;
+                } else if let Some(ref s) = tcx.dep_graph.dep_node_debug_str(*self) {
+                    write!(f, "{}", s)?;
+                } else {
+                    write!(f, "{:?}", self.hash)?;
+                }
+            } else {
+                write!(f, "{:?}", self.hash)?;
+            }
+            Ok(())
+        })?;
+
+        write!(f, ")")
+    }
+}
+
+
 impl DefPathHash {
     #[inline]
     pub fn to_dep_node(self, kind: DepKind) -> DepNode {
@@ -434,10 +489,11 @@ define_dep_nodes!(
 trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> {
     const CAN_RECONSTRUCT_QUERY_KEY: bool;
     fn to_fingerprint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Fingerprint;
+    fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String;
 }
 
 impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a, T> DepNodeParams<'a, 'gcx, 'tcx> for T
-    where T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
+    where T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>> + fmt::Debug
 {
     default const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
 
@@ -449,6 +505,10 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a, T> DepNodeParams<'a, 'gcx, 'tcx> for T
 
         hasher.finish()
     }
+
+    default fn to_debug_str(&self, _: TyCtxt<'a, 'gcx, 'tcx>) -> String {
+        format!("{:?}", *self)
+    }
 }
 
 impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId,) {
@@ -457,6 +517,62 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId,) {
     fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
         tcx.def_path_hash(self.0).0
     }
+
+    fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
+        tcx.item_path_str(self.0)
+    }
+}
+
+impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId, DefId) {
+    const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
+
+    fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
+        let (def_id_0, def_id_1) = *self;
+
+        let def_path_hash_0 = tcx.def_path_hash(def_id_0);
+        let def_path_hash_1 = tcx.def_path_hash(def_id_1);
+
+        def_path_hash_0.0.combine(def_path_hash_1.0)
+    }
+
+    fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
+        let (def_id_0, def_id_1) = *self;
+
+        format!("({}, {})",
+                tcx.def_path(def_id_0).to_string(tcx),
+                tcx.def_path(def_id_1).to_string(tcx))
+    }
+}
+
+
+impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefIdList,) {
+    const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
+
+    fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
+        let mut fingerprint = Fingerprint::zero();
+
+        for &def_id in self.0.iter() {
+            let def_path_hash = tcx.def_path_hash(def_id);
+            fingerprint = fingerprint.combine(def_path_hash.0);
+        }
+
+        fingerprint
+    }
+
+    fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
+        use std::fmt::Write;
+
+        let mut s = String::new();
+        write!(&mut s, "[").unwrap();
+
+        for &def_id in self.0.iter() {
+            write!(&mut s, "{}", tcx.def_path(def_id).to_string(tcx)).unwrap();
+        }
+
+        write!(&mut s, "]").unwrap();
+
+        s
+    }
 }
 
 /// A "work product" corresponds to a `.o` (or other) file that we
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 6afd31bfe92..e48e61d8035 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -37,6 +37,8 @@ struct DepGraphData {
 
     /// Work-products that we generate in this run.
     work_products: RefCell<FxHashMap<WorkProductId, WorkProduct>>,
+
+    dep_node_debug: RefCell<FxHashMap<DepNode, String>>,
 }
 
 impl DepGraph {
@@ -46,6 +48,7 @@ impl DepGraph {
                 thread: DepGraphThreadData::new(enabled),
                 previous_work_products: RefCell::new(FxHashMap()),
                 work_products: RefCell::new(FxHashMap()),
+                dep_node_debug: RefCell::new(FxHashMap()),
             })
         }
     }
@@ -152,6 +155,22 @@ impl DepGraph {
     pub fn previous_work_products(&self) -> Ref<FxHashMap<WorkProductId, WorkProduct>> {
         self.data.previous_work_products.borrow()
     }
+
+    #[inline(always)]
+    pub(super) fn register_dep_node_debug_str<F>(&self,
+                                                 dep_node: DepNode,
+                                                 debug_str_gen: F)
+        where F: FnOnce() -> String
+    {
+        let mut dep_node_debug = self.data.dep_node_debug.borrow_mut();
+
+        dep_node_debug.entry(dep_node)
+                      .or_insert_with(debug_str_gen);
+    }
+
+    pub(super) fn dep_node_debug_str(&self, dep_node: DepNode) -> Option<String> {
+        self.data.dep_node_debug.borrow().get(&dep_node).cloned()
+    }
 }
 
 /// A "work product" is an intermediate result that we save into the
diff --git a/src/librustc/ich/fingerprint.rs b/src/librustc/ich/fingerprint.rs
index 8308c756c05..2391b61253a 100644
--- a/src/librustc/ich/fingerprint.rs
+++ b/src/librustc/ich/fingerprint.rs
@@ -31,9 +31,20 @@ impl Fingerprint {
         self.0
     }
 
+    #[inline]
+    pub fn combine(self, other: Fingerprint) -> Fingerprint {
+        // See https://stackoverflow.com/a/27952689 on why this function is
+        // implemented this way.
+        Fingerprint(
+            self.0.wrapping_mul(3).wrapping_add(other.0),
+            self.1.wrapping_mul(3).wrapping_add(other.1)
+        )
+    }
+
     pub fn to_hex(&self) -> String {
         format!("{:x}{:x}", self.0, self.1)
     }
+
 }
 
 impl ::std::fmt::Display for Fingerprint {