9
9
// except according to those terms.
10
10
11
11
use rustc:: hir;
12
- use rustc:: mir:: { Local , Location , Place , Mir , Rvalue } ;
12
+ use rustc:: mir:: { BasicBlock , BasicBlockData , Location , Place , Mir , Rvalue } ;
13
13
use rustc:: mir:: visit:: Visitor ;
14
14
use rustc:: mir:: Place :: Projection ;
15
- use rustc:: mir:: { PlaceProjection , ProjectionElem } ;
15
+ use rustc:: mir:: { Local , PlaceProjection , ProjectionElem } ;
16
+ use rustc:: mir:: visit:: TyContext ;
16
17
use rustc:: infer:: InferCtxt ;
17
18
use rustc:: traits:: { self , ObligationCause } ;
18
- use rustc:: ty:: { self , Ty } ;
19
+ use rustc:: ty:: { self , ClosureSubsts , Ty } ;
20
+ use rustc:: ty:: subst:: Substs ;
19
21
use rustc:: ty:: fold:: TypeFoldable ;
20
22
use rustc:: util:: common:: ErrorReported ;
21
23
use rustc_data_structures:: fx:: FxHashSet ;
22
24
use syntax:: codemap:: DUMMY_SP ;
23
25
use borrow_check:: FlowInProgress ;
24
26
use dataflow:: MaybeInitializedLvals ;
25
- use dataflow:: move_paths:: { MoveData , HasMoveData } ;
27
+ use dataflow:: move_paths:: { HasMoveData , MoveData } ;
26
28
27
29
use super :: LivenessResults ;
28
30
use super :: ToRegionVid ;
@@ -37,15 +39,19 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
37
39
flow_inits : & mut FlowInProgress < MaybeInitializedLvals < ' cx , ' gcx , ' tcx > > ,
38
40
move_data : & MoveData < ' tcx > ,
39
41
) {
40
- ConstraintGeneration {
42
+ let mut cg = ConstraintGeneration {
41
43
infcx,
42
44
regioncx,
43
45
mir,
44
46
liveness,
45
47
param_env,
46
48
flow_inits,
47
49
move_data,
48
- } . add_constraints ( ) ;
50
+ } ;
51
+
52
+ for ( bb, data) in mir. basic_blocks ( ) . iter_enumerated ( ) {
53
+ cg. visit_basic_block_data ( bb, data) ;
54
+ }
49
55
}
50
56
51
57
/// 'cg = the duration of the constraint generation process itself.
@@ -59,75 +65,147 @@ struct ConstraintGeneration<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> {
59
65
move_data : & ' cg MoveData < ' tcx > ,
60
66
}
61
67
62
- impl < ' cx , ' cg , ' gcx , ' tcx > ConstraintGeneration < ' cx , ' cg , ' gcx , ' tcx > {
63
- fn add_constraints ( & mut self ) {
64
- self . add_liveness_constraints ( ) ;
65
- self . add_borrow_constraints ( ) ;
68
+
69
+ impl < ' cg , ' cx , ' gcx , ' tcx > Visitor < ' tcx > for ConstraintGeneration < ' cg , ' cx , ' gcx , ' tcx > {
70
+ fn visit_basic_block_data ( & mut self , bb : BasicBlock , data : & BasicBlockData < ' tcx > ) {
71
+ self . add_liveness_constraints ( bb) ;
72
+ self . super_basic_block_data ( bb, data) ;
73
+ }
74
+
75
+ /// We sometimes have `substs` within an rvalue, or within a
76
+ /// call. Make them live at the location where they appear.
77
+ fn visit_substs ( & mut self , substs : & & ' tcx Substs < ' tcx > , location : Location ) {
78
+ self . add_regular_live_constraint ( * substs, location) ;
79
+ self . super_substs ( substs) ;
80
+ }
81
+
82
+ /// We sometimes have `region` within an rvalue, or within a
83
+ /// call. Make them live at the location where they appear.
84
+ fn visit_region ( & mut self , region : & ty:: Region < ' tcx > , location : Location ) {
85
+ self . add_regular_live_constraint ( * region, location) ;
86
+ self . super_region ( region) ;
66
87
}
67
88
89
+ /// We sometimes have `ty` within an rvalue, or within a
90
+ /// call. Make them live at the location where they appear.
91
+ fn visit_ty ( & mut self , ty : & ty:: Ty < ' tcx > , ty_context : TyContext ) {
92
+ match ty_context {
93
+ TyContext :: ReturnTy ( source_info) |
94
+ TyContext :: LocalDecl { source_info, .. } => {
95
+ span_bug ! ( source_info. span,
96
+ "should not be visiting outside of the CFG: {:?}" ,
97
+ ty_context) ;
98
+ }
99
+ TyContext :: Location ( location) => {
100
+ self . add_regular_live_constraint ( * ty, location) ;
101
+ }
102
+ }
103
+
104
+ self . super_ty ( ty) ;
105
+ }
106
+
107
+ /// We sometimes have `closure_substs` within an rvalue, or within a
108
+ /// call. Make them live at the location where they appear.
109
+ fn visit_closure_substs ( & mut self , substs : & ClosureSubsts < ' tcx > , location : Location ) {
110
+ self . add_regular_live_constraint ( * substs, location) ;
111
+ self . super_closure_substs ( substs) ;
112
+ }
113
+
114
+ fn visit_rvalue ( & mut self , rvalue : & Rvalue < ' tcx > , location : Location ) {
115
+ debug ! ( "visit_rvalue(rvalue={:?}, location={:?})" , rvalue, location) ;
116
+
117
+ // Look for an rvalue like:
118
+ //
119
+ // & L
120
+ //
121
+ // where L is the path that is borrowed. In that case, we have
122
+ // to add the reborrow constraints (which don't fall out
123
+ // naturally from the type-checker).
124
+ if let Rvalue :: Ref ( region, _bk, ref borrowed_lv) = * rvalue {
125
+ self . add_reborrow_constraint ( location, region, borrowed_lv) ;
126
+ }
127
+
128
+ self . super_rvalue ( rvalue, location) ;
129
+ }
130
+ }
131
+
132
+ impl < ' cx , ' cg , ' gcx , ' tcx > ConstraintGeneration < ' cx , ' cg , ' gcx , ' tcx > {
68
133
/// Liveness constraints:
69
134
///
70
135
/// > If a variable V is live at point P, then all regions R in the type of V
71
136
/// > must include the point P.
72
- fn add_liveness_constraints ( & mut self ) {
73
- debug ! ( "add_liveness_constraints()" ) ;
74
- for bb in self . mir . basic_blocks ( ) . indices ( ) {
75
- debug ! ( "add_liveness_constraints: bb={:?}" , bb) ;
76
-
77
- self . liveness
78
- . regular
79
- . simulate_block ( self . mir , bb, |location, live_locals| {
80
- for live_local in live_locals. iter ( ) {
81
- let live_local_ty = self . mir . local_decls [ live_local] . ty ;
82
- self . add_regular_live_constraint ( live_local_ty, location) ;
83
- }
84
- } ) ;
137
+ fn add_liveness_constraints ( & mut self , bb : BasicBlock ) {
138
+ debug ! ( "add_liveness_constraints(bb={:?})" , bb) ;
85
139
86
- let mut all_live_locals: Vec < ( Location , Vec < Local > ) > = vec ! [ ] ;
87
- self . liveness . drop . simulate_block ( self . mir , bb, |location, live_locals| {
140
+ self . liveness
141
+ . regular
142
+ . simulate_block ( self . mir , bb, |location, live_locals| {
143
+ for live_local in live_locals. iter ( ) {
144
+ let live_local_ty = self . mir . local_decls [ live_local] . ty ;
145
+ self . add_regular_live_constraint ( live_local_ty, location) ;
146
+ }
147
+ } ) ;
148
+
149
+ let mut all_live_locals: Vec < ( Location , Vec < Local > ) > = vec ! [ ] ;
150
+ self . liveness
151
+ . drop
152
+ . simulate_block ( self . mir , bb, |location, live_locals| {
88
153
all_live_locals. push ( ( location, live_locals. iter ( ) . collect ( ) ) ) ;
89
154
} ) ;
90
- debug ! ( "add_liveness_constraints: all_live_locals={:#?}" , all_live_locals) ;
91
-
92
- let terminator_index = self . mir . basic_blocks ( ) [ bb] . statements . len ( ) ;
93
- self . flow_inits . reset_to_entry_of ( bb) ;
94
- while let Some ( ( location, live_locals) ) = all_live_locals. pop ( ) {
95
- for live_local in live_locals {
96
- debug ! ( "add_liveness_constraints: location={:?} live_local={:?}" , location,
97
- live_local) ;
98
-
99
- self . flow_inits . each_state_bit ( |mpi_init| {
100
- debug ! ( "add_liveness_constraints: location={:?} initialized={:?}" ,
101
- location,
102
- & self . flow_inits
103
- . base_results
104
- . operator( )
105
- . move_data( )
106
- . move_paths[ mpi_init] ) ;
107
- } ) ;
108
-
109
- let mpi = self . move_data . rev_lookup . find_local ( live_local) ;
110
- if let Some ( initialized_child) = self . flow_inits . has_any_child_of ( mpi) {
111
- debug ! ( "add_liveness_constraints: mpi={:?} has initialized child {:?}" ,
112
- self . move_data. move_paths[ mpi] ,
113
- self . move_data. move_paths[ initialized_child] ) ;
114
-
115
- let live_local_ty = self . mir . local_decls [ live_local] . ty ;
116
- self . add_drop_live_constraint ( live_local_ty, location) ;
117
- }
118
- }
155
+ debug ! (
156
+ "add_liveness_constraints: all_live_locals={:#?}" ,
157
+ all_live_locals
158
+ ) ;
119
159
120
- if location. statement_index == terminator_index {
121
- debug ! ( "add_liveness_constraints: reconstruct_terminator_effect from {:#?}" ,
122
- location) ;
123
- self . flow_inits . reconstruct_terminator_effect ( location) ;
124
- } else {
125
- debug ! ( "add_liveness_constraints: reconstruct_statement_effect from {:#?}" ,
126
- location) ;
127
- self . flow_inits . reconstruct_statement_effect ( location) ;
160
+ let terminator_index = self . mir . basic_blocks ( ) [ bb] . statements . len ( ) ;
161
+ self . flow_inits . reset_to_entry_of ( bb) ;
162
+ while let Some ( ( location, live_locals) ) = all_live_locals. pop ( ) {
163
+ for live_local in live_locals {
164
+ debug ! (
165
+ "add_liveness_constraints: location={:?} live_local={:?}" ,
166
+ location,
167
+ live_local
168
+ ) ;
169
+
170
+ self . flow_inits . each_state_bit ( |mpi_init| {
171
+ debug ! (
172
+ "add_liveness_constraints: location={:?} initialized={:?}" ,
173
+ location,
174
+ & self . flow_inits
175
+ . base_results
176
+ . operator( )
177
+ . move_data( )
178
+ . move_paths[ mpi_init]
179
+ ) ;
180
+ } ) ;
181
+
182
+ let mpi = self . move_data . rev_lookup . find_local ( live_local) ;
183
+ if let Some ( initialized_child) = self . flow_inits . has_any_child_of ( mpi) {
184
+ debug ! (
185
+ "add_liveness_constraints: mpi={:?} has initialized child {:?}" ,
186
+ self . move_data. move_paths[ mpi] ,
187
+ self . move_data. move_paths[ initialized_child]
188
+ ) ;
189
+
190
+ let live_local_ty = self . mir . local_decls [ live_local] . ty ;
191
+ self . add_drop_live_constraint ( live_local_ty, location) ;
128
192
}
129
- self . flow_inits . apply_local_effect ( ) ;
130
193
}
194
+
195
+ if location. statement_index == terminator_index {
196
+ debug ! (
197
+ "add_liveness_constraints: reconstruct_terminator_effect from {:#?}" ,
198
+ location
199
+ ) ;
200
+ self . flow_inits . reconstruct_terminator_effect ( location) ;
201
+ } else {
202
+ debug ! (
203
+ "add_liveness_constraints: reconstruct_statement_effect from {:#?}" ,
204
+ location
205
+ ) ;
206
+ self . flow_inits . reconstruct_statement_effect ( location) ;
207
+ }
208
+ self . flow_inits . apply_local_effect ( ) ;
131
209
}
132
210
}
133
211
@@ -185,13 +263,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
185
263
// All things in the `outlives` array may be touched by
186
264
// the destructor and must be live at this point.
187
265
for outlive in outlives {
188
- if let Some ( ty) = outlive. as_type ( ) {
189
- self . add_regular_live_constraint ( ty, location) ;
190
- } else if let Some ( r) = outlive. as_region ( ) {
191
- self . add_regular_live_constraint ( r, location) ;
192
- } else {
193
- bug ! ( )
194
- }
266
+ self . add_regular_live_constraint ( outlive, location) ;
195
267
}
196
268
197
269
// However, there may also be some types that
@@ -228,10 +300,6 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
228
300
}
229
301
}
230
302
231
- fn add_borrow_constraints ( & mut self ) {
232
- self . visit_mir ( self . mir ) ;
233
- }
234
-
235
303
fn add_reborrow_constraint (
236
304
& mut self ,
237
305
location : Location ,
@@ -246,43 +314,24 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
246
314
let base_ty = base. ty ( self . mir , tcx) . to_ty ( tcx) ;
247
315
let base_sty = & base_ty. sty ;
248
316
249
- if let ty:: TyRef ( base_region, ty:: TypeAndMut { ty : _, mutbl } ) = * base_sty {
317
+ if let ty:: TyRef ( base_region, ty:: TypeAndMut { ty : _, mutbl } ) = * base_sty {
250
318
match mutbl {
251
- hir:: Mutability :: MutImmutable => { } ,
319
+ hir:: Mutability :: MutImmutable => { }
252
320
253
321
hir:: Mutability :: MutMutable => {
254
322
self . add_reborrow_constraint ( location, borrow_region, base) ;
255
- } ,
323
+ }
256
324
}
257
325
258
326
let span = self . mir . source_info ( location) . span ;
259
- self . regioncx . add_outlives ( span,
260
- base_region. to_region_vid ( ) ,
261
- borrow_region. to_region_vid ( ) ,
262
- location. successor_within_block ( ) ) ;
327
+ self . regioncx . add_outlives (
328
+ span,
329
+ base_region. to_region_vid ( ) ,
330
+ borrow_region. to_region_vid ( ) ,
331
+ location. successor_within_block ( ) ,
332
+ ) ;
263
333
}
264
334
}
265
335
}
266
336
}
267
337
}
268
-
269
- impl < ' cg , ' cx , ' gcx , ' tcx > Visitor < ' tcx > for ConstraintGeneration < ' cg , ' cx , ' gcx , ' tcx > {
270
- fn visit_rvalue ( & mut self ,
271
- rvalue : & Rvalue < ' tcx > ,
272
- location : Location ) {
273
- debug ! ( "visit_rvalue(rvalue={:?}, location={:?})" , rvalue, location) ;
274
-
275
- // Look for an rvalue like:
276
- //
277
- // & L
278
- //
279
- // where L is the path that is borrowed. In that case, we have
280
- // to add the reborrow constraints (which don't fall out
281
- // naturally from the type-checker).
282
- if let Rvalue :: Ref ( region, _bk, ref borrowed_place) = * rvalue {
283
- self . add_reborrow_constraint ( location, region, borrowed_place) ;
284
- }
285
-
286
- self . super_rvalue ( rvalue, location) ;
287
- }
288
- }
0 commit comments