1 //! This module provides linkage between RegionInferenceContext and
2 //! librustc_graphviz traits, specialized to attaching borrowck analysis
3 //! data to rendered labels.
6 use std
::io
::{self, Write}
;
9 use crate::borrow_check
::constraints
::OutlivesConstraint
;
10 use rustc_graphviz
as dot
;
12 impl<'tcx
> RegionInferenceContext
<'tcx
> {
13 /// Write out the region constraint graph.
14 crate fn dump_graphviz_raw_constraints(&self, mut w
: &mut dyn Write
) -> io
::Result
<()> {
15 dot
::render(&RawConstraints { regioncx: self }
, &mut w
)
18 /// Write out the region constraint graph.
19 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();
23 for region
in self.definitions
.indices() {
24 let scc
= self.constraint_sccs
.scc(region
);
25 nodes_per_scc
[scc
].push(region
);
28 dot
::render(&SccConstraints { regioncx: self, nodes_per_scc }
, &mut w
)
32 struct RawConstraints
<'a
, 'tcx
> {
33 regioncx
: &'a RegionInferenceContext
<'tcx
>,
36 impl<'a
, 'this
, 'tcx
> dot
::Labeller
<'this
> for RawConstraints
<'a
, 'tcx
> {
37 type Node
= RegionVid
;
38 type Edge
= OutlivesConstraint
;
40 fn graph_id(&'this
self) -> dot
::Id
<'this
> {
41 dot
::Id
::new("RegionInferenceContext").unwrap()
43 fn node_id(&'this
self, n
: &RegionVid
) -> dot
::Id
<'this
> {
44 dot
::Id
::new(format
!("r{}", n
.index())).unwrap()
46 fn node_shape(&'this
self, _node
: &RegionVid
) -> Option
<dot
::LabelText
<'this
>> {
47 Some(dot
::LabelText
::LabelStr(Cow
::Borrowed("box")))
49 fn node_label(&'this
self, n
: &RegionVid
) -> dot
::LabelText
<'this
> {
50 dot
::LabelText
::LabelStr(format
!("{:?}", n
).into())
52 fn edge_label(&'this
self, e
: &OutlivesConstraint
) -> dot
::LabelText
<'this
> {
53 dot
::LabelText
::LabelStr(format
!("{:?}", e
.locations
).into())
57 impl<'a
, 'this
, 'tcx
> dot
::GraphWalk
<'this
> for RawConstraints
<'a
, 'tcx
> {
58 type Node
= RegionVid
;
59 type Edge
= OutlivesConstraint
;
61 fn nodes(&'this
self) -> dot
::Nodes
<'this
, RegionVid
> {
62 let vids
: Vec
<RegionVid
> = self.regioncx
.definitions
.indices().collect();
65 fn edges(&'this
self) -> dot
::Edges
<'this
, OutlivesConstraint
> {
66 (&self.regioncx
.constraints
.outlives().raw
[..]).into()
69 // Render `a: b` as `a -> b`, indicating the flow
70 // of data during inference.
72 fn source(&'this
self, edge
: &OutlivesConstraint
) -> RegionVid
{
76 fn target(&'this
self, edge
: &OutlivesConstraint
) -> RegionVid
{
81 struct SccConstraints
<'a
, 'tcx
> {
82 regioncx
: &'a RegionInferenceContext
<'tcx
>,
83 nodes_per_scc
: IndexVec
<ConstraintSccIndex
, Vec
<RegionVid
>>,
86 impl<'a
, 'this
, 'tcx
> dot
::Labeller
<'this
> for SccConstraints
<'a
, 'tcx
> {
87 type Node
= ConstraintSccIndex
;
88 type Edge
= (ConstraintSccIndex
, ConstraintSccIndex
);
90 fn graph_id(&'this
self) -> dot
::Id
<'this
> {
91 dot
::Id
::new("RegionInferenceContext".to_string()).unwrap()
93 fn node_id(&'this
self, n
: &ConstraintSccIndex
) -> dot
::Id
<'this
> {
94 dot
::Id
::new(format
!("r{}", n
.index())).unwrap()
96 fn node_shape(&'this
self, _node
: &ConstraintSccIndex
) -> Option
<dot
::LabelText
<'this
>> {
97 Some(dot
::LabelText
::LabelStr(Cow
::Borrowed("box")))
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())
105 impl<'a
, 'this
, 'tcx
> dot
::GraphWalk
<'this
> for SccConstraints
<'a
, 'tcx
> {
106 type Node
= ConstraintSccIndex
;
107 type Edge
= (ConstraintSccIndex
, ConstraintSccIndex
);
109 fn nodes(&'this
self) -> dot
::Nodes
<'this
, ConstraintSccIndex
> {
110 let vids
: Vec
<ConstraintSccIndex
> = self.regioncx
.constraint_sccs
.all_sccs().collect();
113 fn edges(&'this
self) -> dot
::Edges
<'this
, (ConstraintSccIndex
, ConstraintSccIndex
)> {
114 let edges
: Vec
<_
> = self
123 .map(move |&scc_b
| (scc_a
, scc_b
))
130 // Render `a: b` as `a -> b`, indicating the flow
131 // of data during inference.
133 fn source(&'this
self, edge
: &(ConstraintSccIndex
, ConstraintSccIndex
)) -> ConstraintSccIndex
{
137 fn target(&'this
self, edge
: &(ConstraintSccIndex
, ConstraintSccIndex
)) -> ConstraintSccIndex
{