88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- use borrow_check:: nll:: constraints:: { ConstraintIndex , ConstraintSet } ;
11+ use borrow_check:: nll:: constraints:: { ConstraintIndex , ConstraintSet , OutlivesConstraint } ;
1212use rustc:: ty:: RegionVid ;
1313use rustc_data_structures:: graph;
1414use rustc_data_structures:: indexed_vec:: IndexVec ;
1515
16- crate struct ConstraintGraph {
16+ /// The construct graph organizes the constraints by their end-points.
17+ /// It can be used to view a `R1: R2` constraint as either an edge `R1
18+ /// -> R2` or `R2 -> R1` depending on the direction type `D`.
19+ crate struct ConstraintGraph < D : ConstraintGraphDirecton > {
20+ _direction : D ,
1721 first_constraints : IndexVec < RegionVid , Option < ConstraintIndex > > ,
1822 next_constraints : IndexVec < ConstraintIndex , Option < ConstraintIndex > > ,
1923}
2024
21- impl ConstraintGraph {
25+ crate type NormalConstraintGraph = ConstraintGraph < Normal > ;
26+
27+ crate type ReverseConstraintGraph = ConstraintGraph < Reverse > ;
28+
29+ /// Marker trait that controls whether a `R1: R2` constraint
30+ /// represents an edge `R1 -> R2` or `R2 -> R1`.
31+ crate trait ConstraintGraphDirecton : Copy + ' static {
32+ fn start_region ( c : & OutlivesConstraint ) -> RegionVid ;
33+ fn end_region ( c : & OutlivesConstraint ) -> RegionVid ;
34+ }
35+
36+ /// In normal mode, a `R1: R2` constraint results in an edge `R1 ->
37+ /// R2`. This is what we use when constructing the SCCs for
38+ /// inference. This is because we compute the value of R1 by union'ing
39+ /// all the things that it relies on.
40+ #[ derive( Copy , Clone , Debug ) ]
41+ crate struct Normal ;
42+
43+ impl ConstraintGraphDirecton for Normal {
44+ fn start_region ( c : & OutlivesConstraint ) -> RegionVid {
45+ c. sup
46+ }
47+
48+ fn end_region ( c : & OutlivesConstraint ) -> RegionVid {
49+ c. sub
50+ }
51+ }
52+
53+ /// In reverse mode, a `R1: R2` constraint results in an edge `R2 ->
54+ /// R1`. We use this for optimizing liveness computation, because then
55+ /// we wish to iterate from a region (e.g., R2) to all the regions
56+ /// that will outlive it (e.g., R1).
57+ #[ derive( Copy , Clone , Debug ) ]
58+ crate struct Reverse ;
59+
60+ impl ConstraintGraphDirecton for Reverse {
61+ fn start_region ( c : & OutlivesConstraint ) -> RegionVid {
62+ c. sub
63+ }
64+
65+ fn end_region ( c : & OutlivesConstraint ) -> RegionVid {
66+ c. sup
67+ }
68+ }
69+
70+ impl < D : ConstraintGraphDirecton > ConstraintGraph < D > {
2271 /// Create a "dependency graph" where each region constraint `R1:
2372 /// R2` is treated as an edge `R1 -> R2`. We use this graph to
2473 /// construct SCCs for region inference but also for error
2574 /// reporting.
26- crate fn new ( set : & ConstraintSet , num_region_vars : usize ) -> Self {
75+ crate fn new (
76+ direction : D ,
77+ set : & ConstraintSet ,
78+ num_region_vars : usize ,
79+ ) -> Self {
2780 let mut first_constraints = IndexVec :: from_elem_n ( None , num_region_vars) ;
2881 let mut next_constraints = IndexVec :: from_elem ( None , & set. constraints ) ;
2982
3083 for ( idx, constraint) in set. constraints . iter_enumerated ( ) . rev ( ) {
31- let head = & mut first_constraints[ constraint. sup ] ;
84+ let head = & mut first_constraints[ D :: start_region ( constraint) ] ;
3285 let next = & mut next_constraints[ idx] ;
3386 debug_assert ! ( next. is_none( ) ) ;
3487 * next = * head;
3588 * head = Some ( idx) ;
3689 }
3790
3891 Self {
92+ _direction : direction,
3993 first_constraints,
4094 next_constraints,
4195 }
4296 }
4397
98+ /// Given the constraint set from which this graph was built
99+ /// creates a region graph so that you can iterate over *regions*
100+ /// and not constraints.
101+ crate fn region_graph < ' rg > ( & ' rg self , set : & ' rg ConstraintSet ) -> RegionGraph < ' rg , D > {
102+ RegionGraph :: new ( set, self )
103+ }
104+
44105 /// Given a region `R`, iterate over all constraints `R: R1`.
45- crate fn outgoing_edges ( & self , region_sup : RegionVid ) -> Edges < ' _ > {
106+ crate fn outgoing_edges ( & self , region_sup : RegionVid ) -> Edges < ' _ , D > {
46107 let first = self . first_constraints [ region_sup] ;
47108 Edges {
48109 graph : self ,
@@ -51,12 +112,12 @@ impl ConstraintGraph {
51112 }
52113}
53114
54- crate struct Edges < ' s > {
55- graph : & ' s ConstraintGraph ,
115+ crate struct Edges < ' s , D : ConstraintGraphDirecton > {
116+ graph : & ' s ConstraintGraph < D > ,
56117 pointer : Option < ConstraintIndex > ,
57118}
58119
59- impl < ' s > Iterator for Edges < ' s > {
120+ impl < ' s , D : ConstraintGraphDirecton > Iterator for Edges < ' s , D > {
60121 type Item = ConstraintIndex ;
61122
62123 fn next ( & mut self ) -> Option < Self :: Item > {
@@ -69,17 +130,20 @@ impl<'s> Iterator for Edges<'s> {
69130 }
70131}
71132
72- crate struct RegionGraph < ' s > {
133+ /// This struct brings together a constraint set and a (normal, not
134+ /// reverse) constraint graph. It implements the graph traits and is
135+ /// usd for doing the SCC computation.
136+ crate struct RegionGraph < ' s , D : ConstraintGraphDirecton > {
73137 set : & ' s ConstraintSet ,
74- constraint_graph : & ' s ConstraintGraph ,
138+ constraint_graph : & ' s ConstraintGraph < D > ,
75139}
76140
77- impl < ' s > RegionGraph < ' s > {
141+ impl < ' s , D : ConstraintGraphDirecton > RegionGraph < ' s , D > {
78142 /// Create a "dependency graph" where each region constraint `R1:
79143 /// R2` is treated as an edge `R1 -> R2`. We use this graph to
80144 /// construct SCCs for region inference but also for error
81145 /// reporting.
82- crate fn new ( set : & ' s ConstraintSet , constraint_graph : & ' s ConstraintGraph ) -> Self {
146+ crate fn new ( set : & ' s ConstraintSet , constraint_graph : & ' s ConstraintGraph < D > ) -> Self {
83147 Self {
84148 set,
85149 constraint_graph,
@@ -88,47 +152,47 @@ impl<'s> RegionGraph<'s> {
88152
89153 /// Given a region `R`, iterate over all regions `R1` such that
90154 /// there exists a constraint `R: R1`.
91- crate fn sub_regions ( & self , region_sup : RegionVid ) -> Successors < ' _ > {
155+ crate fn outgoing_regions ( & self , region_sup : RegionVid ) -> Successors < ' _ , D > {
92156 Successors {
93157 set : self . set ,
94158 edges : self . constraint_graph . outgoing_edges ( region_sup) ,
95159 }
96160 }
97161}
98162
99- crate struct Successors < ' s > {
163+ crate struct Successors < ' s , D : ConstraintGraphDirecton > {
100164 set : & ' s ConstraintSet ,
101- edges : Edges < ' s > ,
165+ edges : Edges < ' s , D > ,
102166}
103167
104- impl < ' s > Iterator for Successors < ' s > {
168+ impl < ' s , D : ConstraintGraphDirecton > Iterator for Successors < ' s , D > {
105169 type Item = RegionVid ;
106170
107171 fn next ( & mut self ) -> Option < Self :: Item > {
108- self . edges . next ( ) . map ( |c| self . set [ c] . sub )
172+ self . edges . next ( ) . map ( |c| D :: end_region ( & self . set [ c] ) )
109173 }
110174}
111175
112- impl < ' s > graph:: DirectedGraph for RegionGraph < ' s > {
176+ impl < ' s , D : ConstraintGraphDirecton > graph:: DirectedGraph for RegionGraph < ' s , D > {
113177 type Node = RegionVid ;
114178}
115179
116- impl < ' s > graph:: WithNumNodes for RegionGraph < ' s > {
180+ impl < ' s , D : ConstraintGraphDirecton > graph:: WithNumNodes for RegionGraph < ' s , D > {
117181 fn num_nodes ( & self ) -> usize {
118182 self . constraint_graph . first_constraints . len ( )
119183 }
120184}
121185
122- impl < ' s > graph:: WithSuccessors for RegionGraph < ' s > {
186+ impl < ' s , D : ConstraintGraphDirecton > graph:: WithSuccessors for RegionGraph < ' s , D > {
123187 fn successors < ' graph > (
124188 & ' graph self ,
125189 node : Self :: Node ,
126190 ) -> <Self as graph:: GraphSuccessors < ' graph > >:: Iter {
127- self . sub_regions ( node)
191+ self . outgoing_regions ( node)
128192 }
129193}
130194
131- impl < ' s , ' graph > graph:: GraphSuccessors < ' graph > for RegionGraph < ' s > {
195+ impl < ' s , ' graph , D : ConstraintGraphDirecton > graph:: GraphSuccessors < ' graph > for RegionGraph < ' s , D > {
132196 type Item = RegionVid ;
133- type Iter = Successors < ' graph > ;
197+ type Iter = Successors < ' graph , D > ;
134198}
0 commit comments