dump scc graphviz too
This commit is contained in:
parent
d5e77a3c75
commit
3f90bbc556
|
@ -295,9 +295,16 @@ fn dump_mir_results<'a, 'gcx, 'tcx>(
|
|||
// Also dump the inference graph constraints as a graphviz file.
|
||||
let _: io::Result<()> = do catch {
|
||||
let mut file =
|
||||
pretty::create_dump_file(infcx.tcx, "regioncx.dot", None, "nll", &0, source)?;
|
||||
pretty::create_dump_file(infcx.tcx, "regioncx.all.dot", None, "nll", &0, source)?;
|
||||
regioncx.dump_graphviz_raw_constraints(&mut file)?;
|
||||
};
|
||||
|
||||
// Also dump the inference graph constraints as a graphviz file.
|
||||
let _: io::Result<()> = do catch {
|
||||
let mut file =
|
||||
pretty::create_dump_file(infcx.tcx, "regioncx.scc.dot", None, "nll", &0, source)?;
|
||||
regioncx.dump_graphviz_scc_constraints(&mut file)?;
|
||||
};
|
||||
}
|
||||
|
||||
fn dump_annotation<'a, 'gcx, 'tcx>(
|
||||
|
|
|
@ -12,22 +12,37 @@
|
|||
//! libgraphviz traits, specialized to attaching borrowck analysis
|
||||
//! data to rendered labels.
|
||||
|
||||
use super::*;
|
||||
use borrow_check::nll::constraints::OutlivesConstraint;
|
||||
use dot::{self, IntoCow};
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use std::borrow::Cow;
|
||||
use std::io::{self, Write};
|
||||
use super::*;
|
||||
use borrow_check::nll::constraints::OutlivesConstraint;
|
||||
|
||||
impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
/// Write out the region constraint graph.
|
||||
pub(crate) fn dump_graphviz_raw_constraints(&self, mut w: &mut dyn Write) -> io::Result<()> {
|
||||
crate fn dump_graphviz_raw_constraints(&self, mut w: &mut dyn Write) -> io::Result<()> {
|
||||
dot::render(&RawConstraints { regioncx: self }, &mut w)
|
||||
}
|
||||
|
||||
/// Write out the region constraint graph.
|
||||
crate fn dump_graphviz_scc_constraints(&self, mut w: &mut dyn Write) -> io::Result<()> {
|
||||
let mut nodes_per_scc: IndexVec<ConstraintSccIndex, _> = self.constraint_sccs
|
||||
.all_sccs()
|
||||
.map(|_| Vec::new())
|
||||
.collect();
|
||||
|
||||
for region in self.definitions.indices() {
|
||||
let scc = self.constraint_sccs.scc(region);
|
||||
nodes_per_scc[scc].push(region);
|
||||
}
|
||||
|
||||
dot::render(&SccConstraints { regioncx: self, nodes_per_scc }, &mut w)
|
||||
}
|
||||
}
|
||||
|
||||
struct RawConstraints<'a, 'tcx: 'a> {
|
||||
regioncx: &'a RegionInferenceContext<'tcx>
|
||||
regioncx: &'a RegionInferenceContext<'tcx>,
|
||||
}
|
||||
|
||||
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> {
|
|||
(&self.regioncx.constraints.raw[..]).into_cow()
|
||||
}
|
||||
|
||||
// Render `a: b` as `a <- b`, indicating the flow
|
||||
// Render `a: b` as `a -> b`, indicating the flow
|
||||
// of data during inference.
|
||||
|
||||
fn source(&'this self, edge: &OutlivesConstraint) -> RegionVid {
|
||||
edge.sub
|
||||
edge.sup
|
||||
}
|
||||
|
||||
fn target(&'this self, edge: &OutlivesConstraint) -> RegionVid {
|
||||
edge.sup
|
||||
edge.sub
|
||||
}
|
||||
}
|
||||
|
||||
struct SccConstraints<'a, 'tcx: 'a> {
|
||||
regioncx: &'a RegionInferenceContext<'tcx>,
|
||||
nodes_per_scc: IndexVec<ConstraintSccIndex, Vec<RegionVid>>,
|
||||
}
|
||||
|
||||
impl<'a, 'this, 'tcx> dot::Labeller<'this> for SccConstraints<'a, 'tcx> {
|
||||
type Node = ConstraintSccIndex;
|
||||
type Edge = (ConstraintSccIndex, ConstraintSccIndex);
|
||||
|
||||
fn graph_id(&'this self) -> dot::Id<'this> {
|
||||
dot::Id::new(format!("RegionInferenceContext")).unwrap()
|
||||
}
|
||||
fn node_id(&'this self, n: &ConstraintSccIndex) -> dot::Id<'this> {
|
||||
dot::Id::new(format!("r{}", n.index())).unwrap()
|
||||
}
|
||||
fn node_shape(&'this self, _node: &ConstraintSccIndex) -> Option<dot::LabelText<'this>> {
|
||||
Some(dot::LabelText::LabelStr(Cow::Borrowed("box")))
|
||||
}
|
||||
fn node_label(&'this self, n: &ConstraintSccIndex) -> dot::LabelText<'this> {
|
||||
let nodes = &self.nodes_per_scc[*n];
|
||||
dot::LabelText::LabelStr(format!("{:?} = {:?}", n, nodes).into_cow())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'this, 'tcx> dot::GraphWalk<'this> for SccConstraints<'a, 'tcx> {
|
||||
type Node = ConstraintSccIndex;
|
||||
type Edge = (ConstraintSccIndex, ConstraintSccIndex);
|
||||
|
||||
fn nodes(&'this self) -> dot::Nodes<'this, ConstraintSccIndex> {
|
||||
let vids: Vec<ConstraintSccIndex> = self.regioncx.constraint_sccs.all_sccs().collect();
|
||||
vids.into_cow()
|
||||
}
|
||||
fn edges(&'this self) -> dot::Edges<'this, (ConstraintSccIndex, ConstraintSccIndex)> {
|
||||
let edges: Vec<_> = self.regioncx
|
||||
.constraint_sccs
|
||||
.all_sccs()
|
||||
.flat_map(|scc_a| {
|
||||
self.regioncx
|
||||
.constraint_sccs
|
||||
.successors(scc_a)
|
||||
.iter()
|
||||
.map(move |&scc_b| (scc_a, scc_b))
|
||||
})
|
||||
.collect();
|
||||
|
||||
edges.into_cow()
|
||||
}
|
||||
|
||||
// Render `a: b` as `a -> b`, indicating the flow
|
||||
// of data during inference.
|
||||
|
||||
fn source(&'this self, edge: &(ConstraintSccIndex, ConstraintSccIndex)) -> ConstraintSccIndex {
|
||||
edge.0
|
||||
}
|
||||
|
||||
fn target(&'this self, edge: &(ConstraintSccIndex, ConstraintSccIndex)) -> ConstraintSccIndex {
|
||||
edge.1
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue