]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_borrowck/src/region_infer/graphviz.rs
Remove `crate` visibility usage in compiler
[rust.git] / compiler / rustc_borrowck / src / region_infer / graphviz.rs
1 //! This module provides linkage between RegionInferenceContext and
2 //! `rustc_graphviz` traits, specialized to attaching borrowck analysis
3 //! data to rendered labels.
4
5 use std::borrow::Cow;
6 use std::io::{self, Write};
7
8 use super::*;
9 use crate::constraints::OutlivesConstraint;
10 use rustc_graphviz as dot;
11
12 impl<'tcx> RegionInferenceContext<'tcx> {
13     /// Write out the region constraint graph.
14     pub(crate) fn dump_graphviz_raw_constraints(&self, mut w: &mut dyn Write) -> io::Result<()> {
15         dot::render(&RawConstraints { regioncx: self }, &mut w)
16     }
17
18     /// Write out the region constraint graph.
19     pub(crate) fn dump_graphviz_scc_constraints(&self, mut w: &mut dyn Write) -> io::Result<()> {
20         let mut nodes_per_scc: IndexVec<ConstraintSccIndex, _> =
21             self.constraint_sccs.all_sccs().map(|_| Vec::new()).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)
29     }
30 }
31
32 struct RawConstraints<'a, 'tcx> {
33     regioncx: &'a RegionInferenceContext<'tcx>,
34 }
35
36 impl<'a, 'this, 'tcx> dot::Labeller<'this> for RawConstraints<'a, 'tcx> {
37     type Node = RegionVid;
38     type Edge = OutlivesConstraint<'tcx>;
39
40     fn graph_id(&'this self) -> dot::Id<'this> {
41         dot::Id::new("RegionInferenceContext").unwrap()
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> {
50         dot::LabelText::LabelStr(format!("{:?}", n).into())
51     }
52     fn edge_label(&'this self, e: &OutlivesConstraint<'tcx>) -> dot::LabelText<'this> {
53         dot::LabelText::LabelStr(format!("{:?}", e.locations).into())
54     }
55 }
56
57 impl<'a, 'this, 'tcx> dot::GraphWalk<'this> for RawConstraints<'a, 'tcx> {
58     type Node = RegionVid;
59     type Edge = OutlivesConstraint<'tcx>;
60
61     fn nodes(&'this self) -> dot::Nodes<'this, RegionVid> {
62         let vids: Vec<RegionVid> = self.regioncx.definitions.indices().collect();
63         vids.into()
64     }
65     fn edges(&'this self) -> dot::Edges<'this, OutlivesConstraint<'tcx>> {
66         (&self.regioncx.constraints.outlives().raw[..]).into()
67     }
68
69     // Render `a: b` as `a -> b`, indicating the flow
70     // of data during inference.
71
72     fn source(&'this self, edge: &OutlivesConstraint<'tcx>) -> RegionVid {
73         edge.sup
74     }
75
76     fn target(&'this self, edge: &OutlivesConstraint<'tcx>) -> RegionVid {
77         edge.sub
78     }
79 }
80
81 struct SccConstraints<'a, 'tcx> {
82     regioncx: &'a RegionInferenceContext<'tcx>,
83     nodes_per_scc: IndexVec<ConstraintSccIndex, Vec<RegionVid>>,
84 }
85
86 impl<'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];
101         dot::LabelText::LabelStr(format!("{:?} = {:?}", n, nodes).into())
102     }
103 }
104
105 impl<'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();
111         vids.into()
112     }
113     fn edges(&'this self) -> dot::Edges<'this, (ConstraintSccIndex, ConstraintSccIndex)> {
114         let edges: Vec<_> = self
115             .regioncx
116             .constraint_sccs
117             .all_sccs()
118             .flat_map(|scc_a| {
119                 self.regioncx
120                     .constraint_sccs
121                     .successors(scc_a)
122                     .iter()
123                     .map(move |&scc_b| (scc_a, scc_b))
124             })
125             .collect();
126
127         edges.into()
128     }
129
130     // Render `a: b` as `a -> b`, indicating the flow
131     // of data during inference.
132
133     fn source(&'this self, edge: &(ConstraintSccIndex, ConstraintSccIndex)) -> ConstraintSccIndex {
134         edge.0
135     }
136
137     fn target(&'this self, edge: &(ConstraintSccIndex, ConstraintSccIndex)) -> ConstraintSccIndex {
138         edge.1
139     }
140 }