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+ /// Marker trait that controls whether a `R1: R2` constraint
28+ /// represents an edge `R1 -> R2` or `R2 -> R1`.
29+ crate trait ConstraintGraphDirecton : Copy + ' static {
30+ fn start_region ( c : & OutlivesConstraint ) -> RegionVid ;
31+ fn end_region ( c : & OutlivesConstraint ) -> RegionVid ;
32+ }
33+
34+ /// In normal mode, a `R1: R2` constraint results in an edge `R1 ->
35+ /// R2`. This is what we use when constructing the SCCs for
36+ /// inference. This is because we compute the value of R1 by union'ing
37+ /// all the things that it relies on.
38+ #[ derive( Copy , Clone , Debug ) ]
39+ crate struct Normal ;
40+
41+ impl ConstraintGraphDirecton for Normal {
42+ fn start_region ( c : & OutlivesConstraint ) -> RegionVid {
43+ c. sup
44+ }
45+
46+ fn end_region ( c : & OutlivesConstraint ) -> RegionVid {
47+ c. sub
48+ }
49+ }
50+
51+ /// In reverse mode, a `R1: R2` constraint results in an edge `R2 ->
52+ /// R1`. We use this for optimizing liveness computation, because then
53+ /// we wish to iterate from a region (e.g., R2) to all the regions
54+ /// that will outlive it (e.g., R1).
55+ #[ derive( Copy , Clone , Debug ) ]
56+ crate struct Reverse ;
57+
58+ impl ConstraintGraphDirecton for Reverse {
59+ fn start_region ( c : & OutlivesConstraint ) -> RegionVid {
60+ c. sub
61+ }
62+
63+ fn end_region ( c : & OutlivesConstraint ) -> RegionVid {
64+ c. sup
65+ }
66+ }
67+
68+ impl < D : ConstraintGraphDirecton > ConstraintGraph < D > {
2269 /// Create a "dependency graph" where each region constraint `R1:
2370 /// R2` is treated as an edge `R1 -> R2`. We use this graph to
2471 /// construct SCCs for region inference but also for error
2572 /// reporting.
26- crate fn new ( set : & ConstraintSet , num_region_vars : usize ) -> Self {
73+ crate fn new (
74+ direction : D ,
75+ set : & ConstraintSet ,
76+ num_region_vars : usize ,
77+ ) -> Self {
2778 let mut first_constraints = IndexVec :: from_elem_n ( None , num_region_vars) ;
2879 let mut next_constraints = IndexVec :: from_elem ( None , & set. constraints ) ;
2980
3081 for ( idx, constraint) in set. constraints . iter_enumerated ( ) . rev ( ) {
31- let head = & mut first_constraints[ constraint. sup ] ;
82+ let head = & mut first_constraints[ D :: start_region ( constraint) ] ;
3283 let next = & mut next_constraints[ idx] ;
3384 debug_assert ! ( next. is_none( ) ) ;
3485 * next = * head;
3586 * head = Some ( idx) ;
3687 }
3788
3889 Self {
90+ _direction : direction,
3991 first_constraints,
4092 next_constraints,
4193 }
4294 }
4395
96+ /// Given the constraint set from which this graph was built
97+ /// creates a region graph so that you can iterate over *regions*
98+ /// and not constraints.
99+ crate fn region_graph < ' rg > ( & ' rg self , set : & ' rg ConstraintSet ) -> RegionGraph < ' rg , D > {
100+ RegionGraph :: new ( set, self )
101+ }
102+
44103 /// Given a region `R`, iterate over all constraints `R: R1`.
45- crate fn outgoing_edges ( & self , region_sup : RegionVid ) -> Edges < ' _ > {
104+ crate fn outgoing_edges ( & self , region_sup : RegionVid ) -> Edges < ' _ , D > {
46105 let first = self . first_constraints [ region_sup] ;
47106 Edges {
48107 graph : self ,
@@ -51,12 +110,12 @@ impl ConstraintGraph {
51110 }
52111}
53112
54- crate struct Edges < ' s > {
55- graph : & ' s ConstraintGraph ,
113+ crate struct Edges < ' s , D : ConstraintGraphDirecton > {
114+ graph : & ' s ConstraintGraph < D > ,
56115 pointer : Option < ConstraintIndex > ,
57116}
58117
59- impl < ' s > Iterator for Edges < ' s > {
118+ impl < ' s , D : ConstraintGraphDirecton > Iterator for Edges < ' s , D > {
60119 type Item = ConstraintIndex ;
61120
62121 fn next ( & mut self ) -> Option < Self :: Item > {
@@ -69,17 +128,20 @@ impl<'s> Iterator for Edges<'s> {
69128 }
70129}
71130
72- crate struct RegionGraph < ' s > {
131+ /// This struct brings together a constraint set and a (normal, not
132+ /// reverse) constraint graph. It implements the graph traits and is
133+ /// usd for doing the SCC computation.
134+ crate struct RegionGraph < ' s , D : ConstraintGraphDirecton > {
73135 set : & ' s ConstraintSet ,
74- constraint_graph : & ' s ConstraintGraph ,
136+ constraint_graph : & ' s ConstraintGraph < D > ,
75137}
76138
77- impl < ' s > RegionGraph < ' s > {
139+ impl < ' s , D : ConstraintGraphDirecton > RegionGraph < ' s , D > {
78140 /// Create a "dependency graph" where each region constraint `R1:
79141 /// R2` is treated as an edge `R1 -> R2`. We use this graph to
80142 /// construct SCCs for region inference but also for error
81143 /// reporting.
82- crate fn new ( set : & ' s ConstraintSet , constraint_graph : & ' s ConstraintGraph ) -> Self {
144+ crate fn new ( set : & ' s ConstraintSet , constraint_graph : & ' s ConstraintGraph < D > ) -> Self {
83145 Self {
84146 set,
85147 constraint_graph,
@@ -88,47 +150,47 @@ impl<'s> RegionGraph<'s> {
88150
89151 /// Given a region `R`, iterate over all regions `R1` such that
90152 /// there exists a constraint `R: R1`.
91- crate fn sub_regions ( & self , region_sup : RegionVid ) -> Successors < ' _ > {
153+ crate fn outgoing_regions ( & self , region_sup : RegionVid ) -> Successors < ' _ , D > {
92154 Successors {
93155 set : self . set ,
94156 edges : self . constraint_graph . outgoing_edges ( region_sup) ,
95157 }
96158 }
97159}
98160
99- crate struct Successors < ' s > {
161+ crate struct Successors < ' s , D : ConstraintGraphDirecton > {
100162 set : & ' s ConstraintSet ,
101- edges : Edges < ' s > ,
163+ edges : Edges < ' s , D > ,
102164}
103165
104- impl < ' s > Iterator for Successors < ' s > {
166+ impl < ' s , D : ConstraintGraphDirecton > Iterator for Successors < ' s , D > {
105167 type Item = RegionVid ;
106168
107169 fn next ( & mut self ) -> Option < Self :: Item > {
108- self . edges . next ( ) . map ( |c| self . set [ c] . sub )
170+ self . edges . next ( ) . map ( |c| D :: end_region ( & self . set [ c] ) )
109171 }
110172}
111173
112- impl < ' s > graph:: DirectedGraph for RegionGraph < ' s > {
174+ impl < ' s , D : ConstraintGraphDirecton > graph:: DirectedGraph for RegionGraph < ' s , D > {
113175 type Node = RegionVid ;
114176}
115177
116- impl < ' s > graph:: WithNumNodes for RegionGraph < ' s > {
178+ impl < ' s , D : ConstraintGraphDirecton > graph:: WithNumNodes for RegionGraph < ' s , D > {
117179 fn num_nodes ( & self ) -> usize {
118180 self . constraint_graph . first_constraints . len ( )
119181 }
120182}
121183
122- impl < ' s > graph:: WithSuccessors for RegionGraph < ' s > {
184+ impl < ' s , D : ConstraintGraphDirecton > graph:: WithSuccessors for RegionGraph < ' s , D > {
123185 fn successors < ' graph > (
124186 & ' graph self ,
125187 node : Self :: Node ,
126188 ) -> <Self as graph:: GraphSuccessors < ' graph > >:: Iter {
127- self . sub_regions ( node)
189+ self . outgoing_regions ( node)
128190 }
129191}
130192
131- impl < ' s , ' graph > graph:: GraphSuccessors < ' graph > for RegionGraph < ' s > {
193+ impl < ' s , ' graph , D : ConstraintGraphDirecton > graph:: GraphSuccessors < ' graph > for RegionGraph < ' s , D > {
132194 type Item = RegionVid ;
133- type Iter = Successors < ' graph > ;
195+ type Iter = Successors < ' graph , D > ;
134196}
0 commit comments