1
1
use rustc_data_structures:: graph;
2
2
use rustc_index:: IndexVec ;
3
- use rustc_middle:: mir:: ConstraintCategory ;
4
- use rustc_middle:: ty:: { RegionVid , VarianceDiagInfo } ;
5
- use rustc_span:: DUMMY_SP ;
3
+ use rustc_middle:: ty:: RegionVid ;
6
4
7
5
use crate :: constraints:: { OutlivesConstraint , OutlivesConstraintIndex , OutlivesConstraintSet } ;
8
- use crate :: type_check:: Locations ;
9
6
10
7
/// The construct graph organizes the constraints by their end-points.
11
8
/// It can be used to view a `R1: R2` constraint as either an edge `R1
@@ -23,8 +20,8 @@ pub(crate) type ReverseConstraintGraph = ConstraintGraph<Reverse>;
23
20
/// Marker trait that controls whether a `R1: R2` constraint
24
21
/// represents an edge `R1 -> R2` or `R2 -> R1`.
25
22
pub ( crate ) trait ConstraintGraphDirection : Copy + ' static {
26
- fn start_region ( c : & OutlivesConstraint < ' _ > ) -> RegionVid ;
27
- fn end_region ( c : & OutlivesConstraint < ' _ > ) -> RegionVid ;
23
+ fn start_region ( sup : RegionVid , sub : RegionVid ) -> RegionVid ;
24
+ fn end_region ( sup : RegionVid , sub : RegionVid ) -> RegionVid ;
28
25
fn is_normal ( ) -> bool ;
29
26
}
30
27
@@ -36,12 +33,12 @@ pub(crate) trait ConstraintGraphDirection: Copy + 'static {
36
33
pub ( crate ) struct Normal ;
37
34
38
35
impl ConstraintGraphDirection for Normal {
39
- fn start_region ( c : & OutlivesConstraint < ' _ > ) -> RegionVid {
40
- c . sup
36
+ fn start_region ( sup : RegionVid , _sub : RegionVid ) -> RegionVid {
37
+ sup
41
38
}
42
39
43
- fn end_region ( c : & OutlivesConstraint < ' _ > ) -> RegionVid {
44
- c . sub
40
+ fn end_region ( _sup : RegionVid , sub : RegionVid ) -> RegionVid {
41
+ sub
45
42
}
46
43
47
44
fn is_normal ( ) -> bool {
@@ -57,12 +54,12 @@ impl ConstraintGraphDirection for Normal {
57
54
pub ( crate ) struct Reverse ;
58
55
59
56
impl ConstraintGraphDirection for Reverse {
60
- fn start_region ( c : & OutlivesConstraint < ' _ > ) -> RegionVid {
61
- c . sub
57
+ fn start_region ( _sup : RegionVid , sub : RegionVid ) -> RegionVid {
58
+ sub
62
59
}
63
60
64
- fn end_region ( c : & OutlivesConstraint < ' _ > ) -> RegionVid {
65
- c . sup
61
+ fn end_region ( sup : RegionVid , _sub : RegionVid ) -> RegionVid {
62
+ sup
66
63
}
67
64
68
65
fn is_normal ( ) -> bool {
@@ -84,7 +81,7 @@ impl<D: ConstraintGraphDirection> ConstraintGraph<D> {
84
81
let mut next_constraints = IndexVec :: from_elem ( None , & set. outlives ) ;
85
82
86
83
for ( idx, constraint) in set. outlives . iter_enumerated ( ) . rev ( ) {
87
- let head = & mut first_constraints[ D :: start_region ( constraint) ] ;
84
+ let head = & mut first_constraints[ D :: start_region ( constraint. sup , constraint . sub ) ] ;
88
85
let next = & mut next_constraints[ idx] ;
89
86
debug_assert ! ( next. is_none( ) ) ;
90
87
* next = * head;
@@ -105,63 +102,57 @@ impl<D: ConstraintGraphDirection> ConstraintGraph<D> {
105
102
RegionGraph :: new ( set, self , static_region)
106
103
}
107
104
105
+ pub ( crate ) fn is_normal ( & self ) -> bool {
106
+ D :: is_normal ( )
107
+ }
108
+
108
109
/// Given a region `R`, iterate over all constraints `R: R1`.
109
- pub ( crate ) fn outgoing_edges < ' a , ' tcx > (
110
+ pub ( crate ) fn outgoing_edges_vanilla < ' a , ' tcx > (
110
111
& ' a self ,
111
112
region_sup : RegionVid ,
112
113
constraints : & ' a OutlivesConstraintSet < ' tcx > ,
113
- static_region : RegionVid ,
114
- ) -> Edges < ' a , ' tcx , D > {
115
- //if this is the `'static` region and the graph's direction is normal,
116
- //then setup the Edges iterator to return all regions #53178
117
- if region_sup == static_region && D :: is_normal ( ) {
118
- Edges {
119
- graph : self ,
120
- constraints,
121
- pointer : None ,
122
- next_static_idx : Some ( 0 ) ,
123
- static_region,
124
- }
125
- } else {
126
- //otherwise, just setup the iterator as normal
127
- let first = self . first_constraints [ region_sup] ;
128
- Edges { graph : self , constraints, pointer : first, next_static_idx : None , static_region }
129
- }
114
+ ) -> EdgesVanilla < ' a , ' tcx , D > {
115
+ EdgesVanilla { graph : self , constraints, pointer : self . first_constraints [ region_sup] }
116
+ }
117
+
118
+ /// Returns all regions (#53178).
119
+ pub ( crate ) fn outgoing_edges_static ( & self ) -> EdgesStatic {
120
+ EdgesStatic { next_static_idx : 0 , end_static_idx : self . first_constraints . len ( ) }
130
121
}
131
122
}
132
123
133
- pub ( crate ) struct Edges < ' a , ' tcx , D : ConstraintGraphDirection > {
124
+ pub ( crate ) struct EdgesVanilla < ' a , ' tcx , D : ConstraintGraphDirection > {
134
125
graph : & ' a ConstraintGraph < D > ,
135
126
constraints : & ' a OutlivesConstraintSet < ' tcx > ,
136
127
pointer : Option < OutlivesConstraintIndex > ,
137
- next_static_idx : Option < usize > ,
138
- static_region : RegionVid ,
139
128
}
140
129
141
- impl < ' a , ' tcx , D : ConstraintGraphDirection > Iterator for Edges < ' a , ' tcx , D > {
142
- type Item = OutlivesConstraint < ' tcx > ;
130
+ impl < ' a , ' tcx , D : ConstraintGraphDirection > Iterator for EdgesVanilla < ' a , ' tcx , D > {
131
+ type Item = & ' a OutlivesConstraint < ' tcx > ;
143
132
144
133
fn next ( & mut self ) -> Option < Self :: Item > {
145
134
if let Some ( p) = self . pointer {
146
135
self . pointer = self . graph . next_constraints [ p] ;
136
+ Some ( & self . constraints [ p] )
137
+ } else {
138
+ None
139
+ }
140
+ }
141
+ }
142
+
143
+ pub ( crate ) struct EdgesStatic {
144
+ next_static_idx : usize ,
145
+ end_static_idx : usize ,
146
+ }
147
+
148
+ impl Iterator for EdgesStatic {
149
+ type Item = RegionVid ;
147
150
148
- Some ( self . constraints [ p] )
149
- } else if let Some ( next_static_idx) = self . next_static_idx {
150
- self . next_static_idx = if next_static_idx == ( self . graph . first_constraints . len ( ) - 1 ) {
151
- None
152
- } else {
153
- Some ( next_static_idx + 1 )
154
- } ;
155
-
156
- Some ( OutlivesConstraint {
157
- sup : self . static_region ,
158
- sub : next_static_idx. into ( ) ,
159
- locations : Locations :: All ( DUMMY_SP ) ,
160
- span : DUMMY_SP ,
161
- category : ConstraintCategory :: Internal ,
162
- variance_info : VarianceDiagInfo :: default ( ) ,
163
- from_closure : false ,
164
- } )
151
+ fn next ( & mut self ) -> Option < Self :: Item > {
152
+ if self . next_static_idx < self . end_static_idx {
153
+ let ret = RegionVid :: from_usize ( self . next_static_idx ) ;
154
+ self . next_static_idx += 1 ;
155
+ Some ( ret)
165
156
} else {
166
157
None
167
158
}
@@ -193,21 +184,36 @@ impl<'a, 'tcx, D: ConstraintGraphDirection> RegionGraph<'a, 'tcx, D> {
193
184
/// Given a region `R`, iterate over all regions `R1` such that
194
185
/// there exists a constraint `R: R1`.
195
186
pub ( crate ) fn outgoing_regions ( & self , region_sup : RegionVid ) -> Successors < ' a , ' tcx , D > {
196
- Successors {
197
- edges : self . constraint_graph . outgoing_edges ( region_sup, self . set , self . static_region ) ,
187
+ // If this is the `'static` region and the graph's direction is normal,
188
+ // then setup the Edges iterator to return all regions (#53178).
189
+ if region_sup == self . static_region && D :: is_normal ( ) {
190
+ Successors :: Static ( self . constraint_graph . outgoing_edges_static ( ) )
191
+ } else {
192
+ // Otherwise, just setup the iterator as normal.
193
+ Successors :: Vanilla ( self . constraint_graph . outgoing_edges_vanilla ( region_sup, self . set ) )
198
194
}
199
195
}
200
196
}
201
197
202
- pub ( crate ) struct Successors < ' a , ' tcx , D : ConstraintGraphDirection > {
203
- edges : Edges < ' a , ' tcx , D > ,
198
+ pub ( crate ) enum Successors < ' a , ' tcx , D : ConstraintGraphDirection > {
199
+ Static ( EdgesStatic ) ,
200
+ Vanilla ( EdgesVanilla < ' a , ' tcx , D > ) ,
204
201
}
205
202
206
203
impl < ' a , ' tcx , D : ConstraintGraphDirection > Iterator for Successors < ' a , ' tcx , D > {
207
204
type Item = RegionVid ;
208
205
209
206
fn next ( & mut self ) -> Option < Self :: Item > {
210
- self . edges . next ( ) . map ( |c| D :: end_region ( & c) )
207
+ match self {
208
+ Successors :: Static ( static_) => {
209
+ // No `D::end_region` call needed here: static successors are only possible when
210
+ // the direction is `Normal`, so we can directly use what would be the `sub` value.
211
+ static_. next ( )
212
+ }
213
+ Successors :: Vanilla ( vanilla) => {
214
+ vanilla. next ( ) . map ( |constraint| D :: end_region ( constraint. sup , constraint. sub ) )
215
+ }
216
+ }
211
217
}
212
218
}
213
219
0 commit comments