Skip to content

Commit 3f90bbc

Browse files
committed
dump scc graphviz too
1 parent d5e77a3 commit 3f90bbc

File tree

2 files changed

+90
-8
lines changed

2 files changed

+90
-8
lines changed

src/librustc_mir/borrow_check/nll/mod.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,16 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
295295
// Also dump the inference graph constraints as a graphviz file.
296296
let _: io::Result<()> = do catch {
297297
let mut file =
298-
pretty::create_dump_file(infcx.tcx, "regioncx.dot", None, "nll", &0, source)?;
298+
pretty::create_dump_file(infcx.tcx, "regioncx.all.dot", None, "nll", &0, source)?;
299299
regioncx.dump_graphviz_raw_constraints(&mut file)?;
300300
};
301+
302+
// Also dump the inference graph constraints as a graphviz file.
303+
let _: io::Result<()> = do catch {
304+
let mut file =
305+
pretty::create_dump_file(infcx.tcx, "regioncx.scc.dot", None, "nll", &0, source)?;
306+
regioncx.dump_graphviz_scc_constraints(&mut file)?;
307+
};
301308
}
302309

303310
fn dump_annotation<'a, 'gcx, 'tcx>(

src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs

Lines changed: 82 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,37 @@
1212
//! libgraphviz traits, specialized to attaching borrowck analysis
1313
//! data to rendered labels.
1414
15+
use super::*;
16+
use borrow_check::nll::constraints::OutlivesConstraint;
1517
use dot::{self, IntoCow};
1618
use rustc_data_structures::indexed_vec::Idx;
1719
use std::borrow::Cow;
1820
use std::io::{self, Write};
19-
use super::*;
20-
use borrow_check::nll::constraints::OutlivesConstraint;
2121

2222
impl<'tcx> RegionInferenceContext<'tcx> {
2323
/// Write out the region constraint graph.
24-
pub(crate) fn dump_graphviz_raw_constraints(&self, mut w: &mut dyn Write) -> io::Result<()> {
24+
crate fn dump_graphviz_raw_constraints(&self, mut w: &mut dyn Write) -> io::Result<()> {
2525
dot::render(&RawConstraints { regioncx: self }, &mut w)
2626
}
27+
28+
/// Write out the region constraint graph.
29+
crate fn dump_graphviz_scc_constraints(&self, mut w: &mut dyn Write) -> io::Result<()> {
30+
let mut nodes_per_scc: IndexVec<ConstraintSccIndex, _> = self.constraint_sccs
31+
.all_sccs()
32+
.map(|_| Vec::new())
33+
.collect();
34+
35+
for region in self.definitions.indices() {
36+
let scc = self.constraint_sccs.scc(region);
37+
nodes_per_scc[scc].push(region);
38+
}
39+
40+
dot::render(&SccConstraints { regioncx: self, nodes_per_scc }, &mut w)
41+
}
2742
}
2843

2944
struct RawConstraints<'a, 'tcx: 'a> {
30-
regioncx: &'a RegionInferenceContext<'tcx>
45+
regioncx: &'a RegionInferenceContext<'tcx>,
3146
}
3247

3348
impl<'a, 'this, 'tcx> dot::Labeller<'this> for RawConstraints<'a, 'tcx> {
@@ -63,14 +78,74 @@ impl<'a, 'this, 'tcx> dot::GraphWalk<'this> for RawConstraints<'a, 'tcx> {
6378
(&self.regioncx.constraints.raw[..]).into_cow()
6479
}
6580

66-
// Render `a: b` as `a <- b`, indicating the flow
81+
// Render `a: b` as `a -> b`, indicating the flow
6782
// of data during inference.
6883

6984
fn source(&'this self, edge: &OutlivesConstraint) -> RegionVid {
70-
edge.sub
85+
edge.sup
7186
}
7287

7388
fn target(&'this self, edge: &OutlivesConstraint) -> RegionVid {
74-
edge.sup
89+
edge.sub
90+
}
91+
}
92+
93+
struct SccConstraints<'a, 'tcx: 'a> {
94+
regioncx: &'a RegionInferenceContext<'tcx>,
95+
nodes_per_scc: IndexVec<ConstraintSccIndex, Vec<RegionVid>>,
96+
}
97+
98+
impl<'a, 'this, 'tcx> dot::Labeller<'this> for SccConstraints<'a, 'tcx> {
99+
type Node = ConstraintSccIndex;
100+
type Edge = (ConstraintSccIndex, ConstraintSccIndex);
101+
102+
fn graph_id(&'this self) -> dot::Id<'this> {
103+
dot::Id::new(format!("RegionInferenceContext")).unwrap()
104+
}
105+
fn node_id(&'this self, n: &ConstraintSccIndex) -> dot::Id<'this> {
106+
dot::Id::new(format!("r{}", n.index())).unwrap()
107+
}
108+
fn node_shape(&'this self, _node: &ConstraintSccIndex) -> Option<dot::LabelText<'this>> {
109+
Some(dot::LabelText::LabelStr(Cow::Borrowed("box")))
110+
}
111+
fn node_label(&'this self, n: &ConstraintSccIndex) -> dot::LabelText<'this> {
112+
let nodes = &self.nodes_per_scc[*n];
113+
dot::LabelText::LabelStr(format!("{:?} = {:?}", n, nodes).into_cow())
114+
}
115+
}
116+
117+
impl<'a, 'this, 'tcx> dot::GraphWalk<'this> for SccConstraints<'a, 'tcx> {
118+
type Node = ConstraintSccIndex;
119+
type Edge = (ConstraintSccIndex, ConstraintSccIndex);
120+
121+
fn nodes(&'this self) -> dot::Nodes<'this, ConstraintSccIndex> {
122+
let vids: Vec<ConstraintSccIndex> = self.regioncx.constraint_sccs.all_sccs().collect();
123+
vids.into_cow()
124+
}
125+
fn edges(&'this self) -> dot::Edges<'this, (ConstraintSccIndex, ConstraintSccIndex)> {
126+
let edges: Vec<_> = self.regioncx
127+
.constraint_sccs
128+
.all_sccs()
129+
.flat_map(|scc_a| {
130+
self.regioncx
131+
.constraint_sccs
132+
.successors(scc_a)
133+
.iter()
134+
.map(move |&scc_b| (scc_a, scc_b))
135+
})
136+
.collect();
137+
138+
edges.into_cow()
139+
}
140+
141+
// Render `a: b` as `a -> b`, indicating the flow
142+
// of data during inference.
143+
144+
fn source(&'this self, edge: &(ConstraintSccIndex, ConstraintSccIndex)) -> ConstraintSccIndex {
145+
edge.0
146+
}
147+
148+
fn target(&'this self, edge: &(ConstraintSccIndex, ConstraintSccIndex)) -> ConstraintSccIndex {
149+
edge.1
75150
}
76151
}

0 commit comments

Comments
 (0)