]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs
New upstream version 1.40.0+dfsg1
[rustc.git] / src / librustc_mir / borrow_check / nll / region_infer / graphviz.rs
CommitLineData
ff7c6d11
XL
1//! This module provides linkage between RegionInferenceContext and
2//! libgraphviz traits, specialized to attaching borrowck analysis
3//! data to rendered labels.
4
8faf50e0 5use super::*;
9fa01778 6use crate::borrow_check::nll::constraints::OutlivesConstraint;
ff7c6d11
XL
7use std::borrow::Cow;
8use std::io::{self, Write};
ff7c6d11
XL
9
10impl<'tcx> RegionInferenceContext<'tcx> {
11 /// Write out the region constraint graph.
8faf50e0
XL
12 crate fn dump_graphviz_raw_constraints(&self, mut w: &mut dyn Write) -> io::Result<()> {
13 dot::render(&RawConstraints { regioncx: self }, &mut w)
14 }
15
16 /// Write out the region constraint graph.
17 crate fn dump_graphviz_scc_constraints(&self, mut w: &mut dyn Write) -> io::Result<()> {
18 let mut nodes_per_scc: IndexVec<ConstraintSccIndex, _> = self.constraint_sccs
19 .all_sccs()
20 .map(|_| Vec::new())
21 .collect();
22
23 for region in self.definitions.indices() {
24 let scc = self.constraint_sccs.scc(region);
25 nodes_per_scc[scc].push(region);
26 }
27
28 dot::render(&SccConstraints { regioncx: self, nodes_per_scc }, &mut w)
ff7c6d11
XL
29 }
30}
31
dc9dc135 32struct RawConstraints<'a, 'tcx> {
8faf50e0
XL
33 regioncx: &'a RegionInferenceContext<'tcx>,
34}
35
36impl<'a, 'this, 'tcx> dot::Labeller<'this> for RawConstraints<'a, 'tcx> {
ff7c6d11 37 type Node = RegionVid;
94b46f34 38 type Edge = OutlivesConstraint;
ff7c6d11
XL
39
40 fn graph_id(&'this self) -> dot::Id<'this> {
0bf4aa26 41 dot::Id::new("RegionInferenceContext").unwrap()
ff7c6d11
XL
42 }
43 fn node_id(&'this self, n: &RegionVid) -> dot::Id<'this> {
44 dot::Id::new(format!("r{}", n.index())).unwrap()
45 }
46 fn node_shape(&'this self, _node: &RegionVid) -> Option<dot::LabelText<'this>> {
47 Some(dot::LabelText::LabelStr(Cow::Borrowed("box")))
48 }
49 fn node_label(&'this self, n: &RegionVid) -> dot::LabelText<'this> {
0bf4aa26 50 dot::LabelText::LabelStr(format!("{:?}", n).into())
ff7c6d11 51 }
94b46f34 52 fn edge_label(&'this self, e: &OutlivesConstraint) -> dot::LabelText<'this> {
0bf4aa26 53 dot::LabelText::LabelStr(format!("{:?}", e.locations).into())
ff7c6d11
XL
54 }
55}
56
8faf50e0 57impl<'a, 'this, 'tcx> dot::GraphWalk<'this> for RawConstraints<'a, 'tcx> {
ff7c6d11 58 type Node = RegionVid;
94b46f34 59 type Edge = OutlivesConstraint;
ff7c6d11
XL
60
61 fn nodes(&'this self) -> dot::Nodes<'this, RegionVid> {
8faf50e0 62 let vids: Vec<RegionVid> = self.regioncx.definitions.indices().collect();
0bf4aa26 63 vids.into()
ff7c6d11 64 }
94b46f34 65 fn edges(&'this self) -> dot::Edges<'this, OutlivesConstraint> {
dc9dc135 66 (&self.regioncx.constraints.outlives().raw[..]).into()
ff7c6d11
XL
67 }
68
8faf50e0 69 // Render `a: b` as `a -> b`, indicating the flow
ff7c6d11
XL
70 // of data during inference.
71
94b46f34 72 fn source(&'this self, edge: &OutlivesConstraint) -> RegionVid {
8faf50e0 73 edge.sup
ff7c6d11
XL
74 }
75
94b46f34 76 fn target(&'this self, edge: &OutlivesConstraint) -> RegionVid {
8faf50e0
XL
77 edge.sub
78 }
79}
80
dc9dc135 81struct SccConstraints<'a, 'tcx> {
8faf50e0
XL
82 regioncx: &'a RegionInferenceContext<'tcx>,
83 nodes_per_scc: IndexVec<ConstraintSccIndex, Vec<RegionVid>>,
84}
85
86impl<'a, 'this, 'tcx> dot::Labeller<'this> for SccConstraints<'a, 'tcx> {
87 type Node = ConstraintSccIndex;
88 type Edge = (ConstraintSccIndex, ConstraintSccIndex);
89
90 fn graph_id(&'this self) -> dot::Id<'this> {
91 dot::Id::new("RegionInferenceContext".to_string()).unwrap()
92 }
93 fn node_id(&'this self, n: &ConstraintSccIndex) -> dot::Id<'this> {
94 dot::Id::new(format!("r{}", n.index())).unwrap()
95 }
96 fn node_shape(&'this self, _node: &ConstraintSccIndex) -> Option<dot::LabelText<'this>> {
97 Some(dot::LabelText::LabelStr(Cow::Borrowed("box")))
98 }
99 fn node_label(&'this self, n: &ConstraintSccIndex) -> dot::LabelText<'this> {
100 let nodes = &self.nodes_per_scc[*n];
0bf4aa26 101 dot::LabelText::LabelStr(format!("{:?} = {:?}", n, nodes).into())
8faf50e0
XL
102 }
103}
104
105impl<'a, 'this, 'tcx> dot::GraphWalk<'this> for SccConstraints<'a, 'tcx> {
106 type Node = ConstraintSccIndex;
107 type Edge = (ConstraintSccIndex, ConstraintSccIndex);
108
109 fn nodes(&'this self) -> dot::Nodes<'this, ConstraintSccIndex> {
110 let vids: Vec<ConstraintSccIndex> = self.regioncx.constraint_sccs.all_sccs().collect();
0bf4aa26 111 vids.into()
8faf50e0
XL
112 }
113 fn edges(&'this self) -> dot::Edges<'this, (ConstraintSccIndex, ConstraintSccIndex)> {
114 let edges: Vec<_> = self.regioncx
115 .constraint_sccs
116 .all_sccs()
117 .flat_map(|scc_a| {
118 self.regioncx
119 .constraint_sccs
120 .successors(scc_a)
121 .iter()
122 .map(move |&scc_b| (scc_a, scc_b))
123 })
124 .collect();
125
0bf4aa26 126 edges.into()
8faf50e0
XL
127 }
128
129 // Render `a: b` as `a -> b`, indicating the flow
130 // of data during inference.
131
132 fn source(&'this self, edge: &(ConstraintSccIndex, ConstraintSccIndex)) -> ConstraintSccIndex {
133 edge.0
134 }
135
136 fn target(&'this self, edge: &(ConstraintSccIndex, ConstraintSccIndex)) -> ConstraintSccIndex {
137 edge.1
ff7c6d11
XL
138 }
139}