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