8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use borrow_check:: nll:: constraints:: { ConstraintIndex , ConstraintSet } ;
11
+ use borrow_check:: nll:: constraints:: { ConstraintIndex , ConstraintSet , OutlivesConstraint } ;
12
12
use rustc:: ty:: RegionVid ;
13
13
use rustc_data_structures:: graph;
14
14
use rustc_data_structures:: indexed_vec:: IndexVec ;
15
15
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 ,
17
21
first_constraints : IndexVec < RegionVid , Option < ConstraintIndex > > ,
18
22
next_constraints : IndexVec < ConstraintIndex , Option < ConstraintIndex > > ,
19
23
}
20
24
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 > {
22
69
/// Create a "dependency graph" where each region constraint `R1:
23
70
/// R2` is treated as an edge `R1 -> R2`. We use this graph to
24
71
/// construct SCCs for region inference but also for error
25
72
/// 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 {
27
78
let mut first_constraints = IndexVec :: from_elem_n ( None , num_region_vars) ;
28
79
let mut next_constraints = IndexVec :: from_elem ( None , & set. constraints ) ;
29
80
30
81
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) ] ;
32
83
let next = & mut next_constraints[ idx] ;
33
84
debug_assert ! ( next. is_none( ) ) ;
34
85
* next = * head;
35
86
* head = Some ( idx) ;
36
87
}
37
88
38
89
Self {
90
+ _direction : direction,
39
91
first_constraints,
40
92
next_constraints,
41
93
}
42
94
}
43
95
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
+
44
103
/// 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 > {
46
105
let first = self . first_constraints [ region_sup] ;
47
106
Edges {
48
107
graph : self ,
@@ -51,12 +110,12 @@ impl ConstraintGraph {
51
110
}
52
111
}
53
112
54
- crate struct Edges < ' s > {
55
- graph : & ' s ConstraintGraph ,
113
+ crate struct Edges < ' s , D : ConstraintGraphDirecton > {
114
+ graph : & ' s ConstraintGraph < D > ,
56
115
pointer : Option < ConstraintIndex > ,
57
116
}
58
117
59
- impl < ' s > Iterator for Edges < ' s > {
118
+ impl < ' s , D : ConstraintGraphDirecton > Iterator for Edges < ' s , D > {
60
119
type Item = ConstraintIndex ;
61
120
62
121
fn next ( & mut self ) -> Option < Self :: Item > {
@@ -69,17 +128,20 @@ impl<'s> Iterator for Edges<'s> {
69
128
}
70
129
}
71
130
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 > {
73
135
set : & ' s ConstraintSet ,
74
- constraint_graph : & ' s ConstraintGraph ,
136
+ constraint_graph : & ' s ConstraintGraph < D > ,
75
137
}
76
138
77
- impl < ' s > RegionGraph < ' s > {
139
+ impl < ' s , D : ConstraintGraphDirecton > RegionGraph < ' s , D > {
78
140
/// Create a "dependency graph" where each region constraint `R1:
79
141
/// R2` is treated as an edge `R1 -> R2`. We use this graph to
80
142
/// construct SCCs for region inference but also for error
81
143
/// 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 {
83
145
Self {
84
146
set,
85
147
constraint_graph,
@@ -88,47 +150,47 @@ impl<'s> RegionGraph<'s> {
88
150
89
151
/// Given a region `R`, iterate over all regions `R1` such that
90
152
/// 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 > {
92
154
Successors {
93
155
set : self . set ,
94
156
edges : self . constraint_graph . outgoing_edges ( region_sup) ,
95
157
}
96
158
}
97
159
}
98
160
99
- crate struct Successors < ' s > {
161
+ crate struct Successors < ' s , D : ConstraintGraphDirecton > {
100
162
set : & ' s ConstraintSet ,
101
- edges : Edges < ' s > ,
163
+ edges : Edges < ' s , D > ,
102
164
}
103
165
104
- impl < ' s > Iterator for Successors < ' s > {
166
+ impl < ' s , D : ConstraintGraphDirecton > Iterator for Successors < ' s , D > {
105
167
type Item = RegionVid ;
106
168
107
169
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] ) )
109
171
}
110
172
}
111
173
112
- impl < ' s > graph:: DirectedGraph for RegionGraph < ' s > {
174
+ impl < ' s , D : ConstraintGraphDirecton > graph:: DirectedGraph for RegionGraph < ' s , D > {
113
175
type Node = RegionVid ;
114
176
}
115
177
116
- impl < ' s > graph:: WithNumNodes for RegionGraph < ' s > {
178
+ impl < ' s , D : ConstraintGraphDirecton > graph:: WithNumNodes for RegionGraph < ' s , D > {
117
179
fn num_nodes ( & self ) -> usize {
118
180
self . constraint_graph . first_constraints . len ( )
119
181
}
120
182
}
121
183
122
- impl < ' s > graph:: WithSuccessors for RegionGraph < ' s > {
184
+ impl < ' s , D : ConstraintGraphDirecton > graph:: WithSuccessors for RegionGraph < ' s , D > {
123
185
fn successors < ' graph > (
124
186
& ' graph self ,
125
187
node : Self :: Node ,
126
188
) -> <Self as graph:: GraphSuccessors < ' graph > >:: Iter {
127
- self . sub_regions ( node)
189
+ self . outgoing_regions ( node)
128
190
}
129
191
}
130
192
131
- impl < ' s , ' graph > graph:: GraphSuccessors < ' graph > for RegionGraph < ' s > {
193
+ impl < ' s , ' graph , D : ConstraintGraphDirecton > graph:: GraphSuccessors < ' graph > for RegionGraph < ' s , D > {
132
194
type Item = RegionVid ;
133
- type Iter = Successors < ' graph > ;
195
+ type Iter = Successors < ' graph , D > ;
134
196
}
0 commit comments