Skip to content

Commit 05d4880

Browse files
committed
dump scc graphviz too
1 parent 3472813 commit 05d4880

File tree

4 files changed

+119
-16
lines changed

4 files changed

+119
-16
lines changed

Diff for: src/librustc_data_structures/graph/scc/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ impl<N: Idx, S: Idx> Sccs<N, S> {
5454
self.scc_data.len()
5555
}
5656

57+
/// Returns the number of SCCs in the graph.
58+
pub fn all_sccs(&self) -> impl Iterator<Item = S> {
59+
(0 .. self.scc_data.len()).map(S::new)
60+
}
61+
5762
/// Returns the SCC to which a node `r` belongs.
5863
pub fn scc(&self, r: N) -> S {
5964
self.scc_indices[r]

Diff for: src/librustc_mir/borrow_check/nll/mod.rs

+8-1
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>(

Diff for: src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs

+82-7
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.constraints_scc
31+
.all_sccs()
32+
.map(|_| Vec::new())
33+
.collect();
34+
35+
for region in self.definitions.indices() {
36+
let scc = self.constraints_scc.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.constraints_scc.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+
.constraints_scc
128+
.all_sccs()
129+
.flat_map(|scc_a| {
130+
self.regioncx
131+
.constraints_scc
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
}

Diff for: src/librustc_mir/borrow_check/nll/region_infer/mod.rs

+24-8
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
// except according to those terms.
1010

1111
use super::universal_regions::UniversalRegions;
12-
use borrow_check::nll::constraints::{ConstraintIndex, ConstraintSccIndex, ConstraintSet,
13-
OutlivesConstraint};
12+
use borrow_check::nll::constraints::{
13+
ConstraintIndex, ConstraintSccIndex, ConstraintSet, OutlivesConstraint,
14+
};
1415
use borrow_check::nll::region_infer::values::ToElementIndex;
1516
use borrow_check::nll::type_check::Locations;
1617
use rustc::hir::def_id::DefId;
@@ -26,7 +27,8 @@ use rustc::mir::{
2627
use rustc::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable};
2728
use rustc::util::common;
2829
use rustc_data_structures::graph::scc::Sccs;
29-
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
30+
use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf};
31+
use rustc_data_structures::indexed_vec::IndexVec;
3032

3133
use std::rc::Rc;
3234

@@ -402,14 +404,28 @@ impl<'tcx> RegionInferenceContext<'tcx> {
402404
// SCC. For each SCC, we visit its successors and compute
403405
// their values, then we union all those values to get our
404406
// own.
405-
for scc_index in (0..self.constraints_scc.num_sccs()).map(ConstraintSccIndex::new) {
406-
self.propagate_constraints_scc(scc_index);
407+
let visited = &mut IdxSetBuf::new_empty(self.constraints_scc.num_sccs());
408+
for scc_index in self.constraints_scc.all_sccs() {
409+
self.propagate_constraints_scc_if_new(scc_index, visited);
407410
}
408411
}
409412

410-
fn propagate_constraints_scc(&mut self, scc_a: ConstraintSccIndex) {
411-
debug!("propagate_constraints_scc(scc_a = {:?})", scc_a);
413+
#[inline]
414+
fn propagate_constraints_scc_if_new(
415+
&mut self,
416+
scc_a: ConstraintSccIndex,
417+
visited: &mut IdxSet<ConstraintSccIndex>,
418+
) {
419+
if visited.add(&scc_a) {
420+
self.propagate_constraints_scc_new(scc_a, visited);
421+
}
422+
}
412423

424+
fn propagate_constraints_scc_new(
425+
&mut self,
426+
scc_a: ConstraintSccIndex,
427+
visited: &mut IdxSet<ConstraintSccIndex>,
428+
) {
413429
let constraints_scc = self.constraints_scc.clone();
414430

415431
// Walk each SCC `B` such that `A: B`...
@@ -420,7 +436,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
420436
);
421437

422438
// ...compute the value of `B`...
423-
self.propagate_constraints_scc(scc_b);
439+
self.propagate_constraints_scc_if_new(scc_b, visited);
424440

425441
// ...and add elements from `B` into `A`.
426442
self.scc_values.add_region(scc_a, scc_b);

0 commit comments

Comments
 (0)