Skip to content

Commit 119066f

Browse files
committed
Auto merge of #42625 - michaelwoerister:dep-node-debug, r=nikomatsakis
incr.comp.: Make DepNode's std::fmt::Debug implementation useful again. With #42537 a regular `DepNode` only contains an opaque hash as its identifier. In most cases, this hash is actually a `DefPathHash` and we can reconstruct the `DefId` it came from via a table lookup --- and then use that to print something intelligible for debug outputs. For cases where we cannot reconstruct information from the DepNode's hash, this PR will cache a string representation of the `DepNode` in a side-table. This string is later used for debug outputs. r? @nikomatsakis
2 parents 0189cec + e323652 commit 119066f

File tree

3 files changed

+156
-4
lines changed

3 files changed

+156
-4
lines changed

src/librustc/dep_graph/dep_node.rs

+126-4
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ use ich::Fingerprint;
6767
use ty::TyCtxt;
6868
use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
6969
use ich::StableHashingContext;
70+
use std::fmt;
7071
use std::hash::Hash;
7172

7273
// erase!() just makes tokens go away. It's used to specify which macro argument
@@ -145,7 +146,7 @@ macro_rules! define_dep_nodes {
145146
),*
146147
}
147148

148-
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash,
149+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
149150
RustcEncodable, RustcDecodable)]
150151
pub struct DepNode {
151152
pub kind: DepKind,
@@ -166,21 +167,45 @@ macro_rules! define_dep_nodes {
166167
let tupled_args = ( $($tuple_arg,)* );
167168
let hash = DepNodeParams::to_fingerprint(&tupled_args,
168169
tcx);
169-
return DepNode {
170+
let dep_node = DepNode {
170171
kind: DepKind::$variant,
171172
hash
172173
};
174+
175+
if cfg!(debug_assertions) &&
176+
!dep_node.kind.can_reconstruct_query_key() &&
177+
(tcx.sess.opts.debugging_opts.incremental_info ||
178+
tcx.sess.opts.debugging_opts.query_dep_graph)
179+
{
180+
tcx.dep_graph.register_dep_node_debug_str(dep_node, || {
181+
tupled_args.to_debug_str(tcx)
182+
});
183+
}
184+
185+
return dep_node;
173186
})*
174187

175188
// struct args
176189
$({
177190
let tupled_args = ( $($struct_arg_name,)* );
178191
let hash = DepNodeParams::to_fingerprint(&tupled_args,
179192
tcx);
180-
return DepNode {
193+
let dep_node = DepNode {
181194
kind: DepKind::$variant,
182195
hash
183196
};
197+
198+
if cfg!(debug_assertions) &&
199+
!dep_node.kind.can_reconstruct_query_key() &&
200+
(tcx.sess.opts.debugging_opts.incremental_info ||
201+
tcx.sess.opts.debugging_opts.query_dep_graph)
202+
{
203+
tcx.dep_graph.register_dep_node_debug_str(dep_node, || {
204+
tupled_args.to_debug_str(tcx)
205+
});
206+
}
207+
208+
return dep_node;
184209
})*
185210

186211
DepNode {
@@ -267,6 +292,36 @@ macro_rules! define_dep_nodes {
267292
);
268293
}
269294

295+
impl fmt::Debug for DepNode {
296+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
297+
write!(f, "{:?}", self.kind)?;
298+
299+
if !self.kind.has_params() {
300+
return Ok(());
301+
}
302+
303+
write!(f, "(")?;
304+
305+
::ty::tls::with_opt(|opt_tcx| {
306+
if let Some(tcx) = opt_tcx {
307+
if let Some(def_id) = self.extract_def_id(tcx) {
308+
write!(f, "{}", tcx.item_path_str(def_id))?;
309+
} else if let Some(ref s) = tcx.dep_graph.dep_node_debug_str(*self) {
310+
write!(f, "{}", s)?;
311+
} else {
312+
write!(f, "{:?}", self.hash)?;
313+
}
314+
} else {
315+
write!(f, "{:?}", self.hash)?;
316+
}
317+
Ok(())
318+
})?;
319+
320+
write!(f, ")")
321+
}
322+
}
323+
324+
270325
impl DefPathHash {
271326
#[inline]
272327
pub fn to_dep_node(self, kind: DepKind) -> DepNode {
@@ -426,10 +481,11 @@ define_dep_nodes!(
426481
trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> {
427482
const CAN_RECONSTRUCT_QUERY_KEY: bool;
428483
fn to_fingerprint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Fingerprint;
484+
fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String;
429485
}
430486

431487
impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a, T> DepNodeParams<'a, 'gcx, 'tcx> for T
432-
where T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
488+
where T: HashStable<StableHashingContext<'a, 'gcx, 'tcx>> + fmt::Debug
433489
{
434490
default const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
435491

@@ -441,6 +497,10 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a, T> DepNodeParams<'a, 'gcx, 'tcx> for T
441497

442498
hasher.finish()
443499
}
500+
501+
default fn to_debug_str(&self, _: TyCtxt<'a, 'gcx, 'tcx>) -> String {
502+
format!("{:?}", *self)
503+
}
444504
}
445505

446506
impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId,) {
@@ -449,6 +509,68 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId,) {
449509
fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
450510
tcx.def_path_hash(self.0).0
451511
}
512+
513+
fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
514+
tcx.item_path_str(self.0)
515+
}
516+
}
517+
518+
impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefId, DefId) {
519+
const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
520+
521+
// We actually would not need to specialize the implementation of this
522+
// method but it's faster to combine the hashes than to instantiate a full
523+
// hashing context and stable-hashing state.
524+
fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
525+
let (def_id_0, def_id_1) = *self;
526+
527+
let def_path_hash_0 = tcx.def_path_hash(def_id_0);
528+
let def_path_hash_1 = tcx.def_path_hash(def_id_1);
529+
530+
def_path_hash_0.0.combine(def_path_hash_1.0)
531+
}
532+
533+
fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
534+
let (def_id_0, def_id_1) = *self;
535+
536+
format!("({}, {})",
537+
tcx.def_path(def_id_0).to_string(tcx),
538+
tcx.def_path(def_id_1).to_string(tcx))
539+
}
540+
}
541+
542+
543+
impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for (DefIdList,) {
544+
const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
545+
546+
// We actually would not need to specialize the implementation of this
547+
// method but it's faster to combine the hashes than to instantiate a full
548+
// hashing context and stable-hashing state.
549+
fn to_fingerprint(&self, tcx: TyCtxt) -> Fingerprint {
550+
let mut fingerprint = Fingerprint::zero();
551+
552+
for &def_id in self.0.iter() {
553+
let def_path_hash = tcx.def_path_hash(def_id);
554+
fingerprint = fingerprint.combine(def_path_hash.0);
555+
}
556+
557+
fingerprint
558+
}
559+
560+
fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
561+
use std::fmt::Write;
562+
563+
let mut s = String::new();
564+
write!(&mut s, "[").unwrap();
565+
566+
for &def_id in self.0.iter() {
567+
write!(&mut s, "{}", tcx.def_path(def_id).to_string(tcx)).unwrap();
568+
}
569+
570+
write!(&mut s, "]").unwrap();
571+
572+
s
573+
}
452574
}
453575

454576
/// A "work product" corresponds to a `.o` (or other) file that we

src/librustc/dep_graph/graph.rs

+19
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ struct DepGraphData {
3737

3838
/// Work-products that we generate in this run.
3939
work_products: RefCell<FxHashMap<WorkProductId, WorkProduct>>,
40+
41+
dep_node_debug: RefCell<FxHashMap<DepNode, String>>,
4042
}
4143

4244
impl DepGraph {
@@ -46,6 +48,7 @@ impl DepGraph {
4648
thread: DepGraphThreadData::new(enabled),
4749
previous_work_products: RefCell::new(FxHashMap()),
4850
work_products: RefCell::new(FxHashMap()),
51+
dep_node_debug: RefCell::new(FxHashMap()),
4952
})
5053
}
5154
}
@@ -152,6 +155,22 @@ impl DepGraph {
152155
pub fn previous_work_products(&self) -> Ref<FxHashMap<WorkProductId, WorkProduct>> {
153156
self.data.previous_work_products.borrow()
154157
}
158+
159+
#[inline(always)]
160+
pub(super) fn register_dep_node_debug_str<F>(&self,
161+
dep_node: DepNode,
162+
debug_str_gen: F)
163+
where F: FnOnce() -> String
164+
{
165+
let mut dep_node_debug = self.data.dep_node_debug.borrow_mut();
166+
167+
dep_node_debug.entry(dep_node)
168+
.or_insert_with(debug_str_gen);
169+
}
170+
171+
pub(super) fn dep_node_debug_str(&self, dep_node: DepNode) -> Option<String> {
172+
self.data.dep_node_debug.borrow().get(&dep_node).cloned()
173+
}
155174
}
156175

157176
/// A "work product" is an intermediate result that we save into the

src/librustc/ich/fingerprint.rs

+11
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,20 @@ impl Fingerprint {
3131
self.0
3232
}
3333

34+
#[inline]
35+
pub fn combine(self, other: Fingerprint) -> Fingerprint {
36+
// See https://stackoverflow.com/a/27952689 on why this function is
37+
// implemented this way.
38+
Fingerprint(
39+
self.0.wrapping_mul(3).wrapping_add(other.0),
40+
self.1.wrapping_mul(3).wrapping_add(other.1)
41+
)
42+
}
43+
3444
pub fn to_hex(&self) -> String {
3545
format!("{:x}{:x}", self.0, self.1)
3646
}
47+
3748
}
3849

3950
impl ::std::fmt::Display for Fingerprint {

0 commit comments

Comments
 (0)