1 #![deny(rustc::untranslatable_diagnostic)]
2 #![deny(rustc::diagnostic_outside_of_impl)]
3 //! This module provides linkage between RegionInferenceContext and
4 //! `rustc_graphviz` traits, specialized to attaching borrowck analysis
5 //! data to rendered labels.
8 use std::io::{self, Write};
11 use crate::constraints::OutlivesConstraint;
12 use rustc_graphviz as dot;
14 impl<'tcx> RegionInferenceContext<'tcx> {
15 /// Write out the region constraint graph.
16 pub(crate) fn dump_graphviz_raw_constraints(&self, mut w: &mut dyn Write) -> io::Result<()> {
17 dot::render(&RawConstraints { regioncx: self }, &mut w)
20 /// Write out the region constraint graph.
21 pub(crate) fn dump_graphviz_scc_constraints(&self, mut w: &mut dyn Write) -> io::Result<()> {
22 let mut nodes_per_scc: IndexVec<ConstraintSccIndex, _> =
23 self.constraint_sccs.all_sccs().map(|_| Vec::new()).collect();
25 for region in self.definitions.indices() {
26 let scc = self.constraint_sccs.scc(region);
27 nodes_per_scc[scc].push(region);
30 dot::render(&SccConstraints { regioncx: self, nodes_per_scc }, &mut w)
34 struct RawConstraints<'a, 'tcx> {
35 regioncx: &'a RegionInferenceContext<'tcx>,
38 impl<'a, 'this, 'tcx> dot::Labeller<'this> for RawConstraints<'a, 'tcx> {
39 type Node = RegionVid;
40 type Edge = OutlivesConstraint<'tcx>;
42 fn graph_id(&'this self) -> dot::Id<'this> {
43 dot::Id::new("RegionInferenceContext").unwrap()
45 fn node_id(&'this self, n: &RegionVid) -> dot::Id<'this> {
46 dot::Id::new(format!("r{}", n.index())).unwrap()
48 fn node_shape(&'this self, _node: &RegionVid) -> Option<dot::LabelText<'this>> {
49 Some(dot::LabelText::LabelStr(Cow::Borrowed("box")))
51 fn node_label(&'this self, n: &RegionVid) -> dot::LabelText<'this> {
52 dot::LabelText::LabelStr(format!("{:?}", n).into())
54 fn edge_label(&'this self, e: &OutlivesConstraint<'tcx>) -> dot::LabelText<'this> {
55 dot::LabelText::LabelStr(format!("{:?}", e.locations).into())
59 impl<'a, 'this, 'tcx> dot::GraphWalk<'this> for RawConstraints<'a, 'tcx> {
60 type Node = RegionVid;
61 type Edge = OutlivesConstraint<'tcx>;
63 fn nodes(&'this self) -> dot::Nodes<'this, RegionVid> {
64 let vids: Vec<RegionVid> = self.regioncx.definitions.indices().collect();
67 fn edges(&'this self) -> dot::Edges<'this, OutlivesConstraint<'tcx>> {
68 (&self.regioncx.constraints.outlives().raw[..]).into()
71 // Render `a: b` as `a -> b`, indicating the flow
72 // of data during inference.
74 fn source(&'this self, edge: &OutlivesConstraint<'tcx>) -> RegionVid {
78 fn target(&'this self, edge: &OutlivesConstraint<'tcx>) -> RegionVid {
83 struct SccConstraints<'a, 'tcx> {
84 regioncx: &'a RegionInferenceContext<'tcx>,
85 nodes_per_scc: IndexVec<ConstraintSccIndex, Vec<RegionVid>>,
88 impl<'a, 'this, 'tcx> dot::Labeller<'this> for SccConstraints<'a, 'tcx> {
89 type Node = ConstraintSccIndex;
90 type Edge = (ConstraintSccIndex, ConstraintSccIndex);
92 fn graph_id(&'this self) -> dot::Id<'this> {
93 dot::Id::new("RegionInferenceContext".to_string()).unwrap()
95 fn node_id(&'this self, n: &ConstraintSccIndex) -> dot::Id<'this> {
96 dot::Id::new(format!("r{}", n.index())).unwrap()
98 fn node_shape(&'this self, _node: &ConstraintSccIndex) -> Option<dot::LabelText<'this>> {
99 Some(dot::LabelText::LabelStr(Cow::Borrowed("box")))
101 fn node_label(&'this self, n: &ConstraintSccIndex) -> dot::LabelText<'this> {
102 let nodes = &self.nodes_per_scc[*n];
103 dot::LabelText::LabelStr(format!("{:?} = {:?}", n, nodes).into())
107 impl<'a, 'this, 'tcx> dot::GraphWalk<'this> for SccConstraints<'a, 'tcx> {
108 type Node = ConstraintSccIndex;
109 type Edge = (ConstraintSccIndex, ConstraintSccIndex);
111 fn nodes(&'this self) -> dot::Nodes<'this, ConstraintSccIndex> {
112 let vids: Vec<ConstraintSccIndex> = self.regioncx.constraint_sccs.all_sccs().collect();
115 fn edges(&'this self) -> dot::Edges<'this, (ConstraintSccIndex, ConstraintSccIndex)> {
116 let edges: Vec<_> = self
125 .map(move |&scc_b| (scc_a, scc_b))
132 // Render `a: b` as `a -> b`, indicating the flow
133 // of data during inference.
135 fn source(&'this self, edge: &(ConstraintSccIndex, ConstraintSccIndex)) -> ConstraintSccIndex {
139 fn target(&'this self, edge: &(ConstraintSccIndex, ConstraintSccIndex)) -> ConstraintSccIndex {