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:: borrow_set:: BorrowSet ;
12
+ use borrow_check:: location:: LocationTable ;
13
+ use borrow_check:: nll:: facts:: AllFacts ;
11
14
use rustc:: hir;
12
- use rustc:: mir:: { BasicBlock , BasicBlockData , Location , Place , Mir , Rvalue } ;
15
+ use rustc:: infer:: InferCtxt ;
16
+ use rustc:: mir:: visit:: TyContext ;
13
17
use rustc:: mir:: visit:: Visitor ;
14
18
use rustc:: mir:: Place :: Projection ;
15
- use rustc:: mir:: { Local , PlaceProjection , ProjectionElem } ;
16
- use rustc:: mir:: visit:: TyContext ;
17
- use rustc:: infer:: InferCtxt ;
18
- use rustc:: ty:: { self , CanonicalTy , ClosureSubsts } ;
19
- use rustc:: ty:: subst:: Substs ;
19
+ use rustc:: mir:: { BasicBlock , BasicBlockData , Location , Mir , Place , Rvalue } ;
20
+ use rustc:: mir:: { Local , PlaceProjection , ProjectionElem , Statement , Terminator } ;
20
21
use rustc:: ty:: fold:: TypeFoldable ;
22
+ use rustc:: ty:: subst:: Substs ;
23
+ use rustc:: ty:: { self , CanonicalTy , ClosureSubsts } ;
21
24
25
+ use super :: region_infer:: { Cause , RegionInferenceContext } ;
22
26
use super :: ToRegionVid ;
23
- use super :: region_infer:: { RegionInferenceContext , Cause } ;
24
27
25
28
pub ( super ) fn generate_constraints < ' cx , ' gcx , ' tcx > (
26
29
infcx : & InferCtxt < ' cx , ' gcx , ' tcx > ,
27
30
regioncx : & mut RegionInferenceContext < ' tcx > ,
31
+ all_facts : & mut Option < AllFacts > ,
32
+ location_table : & LocationTable ,
28
33
mir : & Mir < ' tcx > ,
34
+ borrow_set : & BorrowSet < ' tcx > ,
29
35
) {
30
36
let mut cg = ConstraintGeneration {
37
+ borrow_set,
31
38
infcx,
32
39
regioncx,
40
+ location_table,
41
+ all_facts,
33
42
mir,
34
43
} ;
35
44
@@ -41,8 +50,11 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
41
50
/// 'cg = the duration of the constraint generation process itself.
42
51
struct ConstraintGeneration < ' cg , ' cx : ' cg , ' gcx : ' tcx , ' tcx : ' cx > {
43
52
infcx : & ' cg InferCtxt < ' cx , ' gcx , ' tcx > ,
53
+ all_facts : & ' cg mut Option < AllFacts > ,
54
+ location_table : & ' cg LocationTable ,
44
55
regioncx : & ' cg mut RegionInferenceContext < ' tcx > ,
45
56
mir : & ' cg Mir < ' tcx > ,
57
+ borrow_set : & ' cg BorrowSet < ' tcx > ,
46
58
}
47
59
48
60
impl < ' cg , ' cx , ' gcx , ' tcx > Visitor < ' tcx > for ConstraintGeneration < ' cg , ' cx , ' gcx , ' tcx > {
@@ -68,12 +80,14 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
68
80
/// call. Make them live at the location where they appear.
69
81
fn visit_ty ( & mut self , ty : & ty:: Ty < ' tcx > , ty_context : TyContext ) {
70
82
match ty_context {
71
- TyContext :: ReturnTy ( source_info) |
72
- TyContext :: YieldTy ( source_info) |
73
- TyContext :: LocalDecl { source_info, .. } => {
74
- span_bug ! ( source_info. span,
75
- "should not be visiting outside of the CFG: {:?}" ,
76
- ty_context) ;
83
+ TyContext :: ReturnTy ( source_info)
84
+ | TyContext :: YieldTy ( source_info)
85
+ | TyContext :: LocalDecl { source_info, .. } => {
86
+ span_bug ! (
87
+ source_info. span,
88
+ "should not be visiting outside of the CFG: {:?}" ,
89
+ ty_context
90
+ ) ;
77
91
}
78
92
TyContext :: Location ( location) => {
79
93
self . add_regular_live_constraint ( * ty, location, Cause :: LiveOther ( location) ) ;
@@ -90,25 +104,117 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
90
104
self . super_closure_substs ( substs) ;
91
105
}
92
106
107
+ fn visit_statement (
108
+ & mut self ,
109
+ block : BasicBlock ,
110
+ statement : & Statement < ' tcx > ,
111
+ location : Location ,
112
+ ) {
113
+ if let Some ( all_facts) = self . all_facts {
114
+ all_facts. cfg_edge . push ( (
115
+ self . location_table . start_index ( location) ,
116
+ self . location_table . mid_index ( location) ,
117
+ ) ) ;
118
+
119
+ all_facts. cfg_edge . push ( (
120
+ self . location_table . mid_index ( location) ,
121
+ self . location_table
122
+ . start_index ( location. successor_within_block ( ) ) ,
123
+ ) ) ;
124
+ }
125
+
126
+ self . super_statement ( block, statement, location) ;
127
+ }
128
+
129
+ fn visit_assign (
130
+ & mut self ,
131
+ block : BasicBlock ,
132
+ place : & Place < ' tcx > ,
133
+ rvalue : & Rvalue < ' tcx > ,
134
+ location : Location ,
135
+ ) {
136
+ // When we see `X = ...`, then kill borrows of
137
+ // `(*X).foo` and so forth.
138
+ if let Some ( all_facts) = self . all_facts {
139
+ if let Place :: Local ( temp) = place {
140
+ if let Some ( borrow_indices) = self . borrow_set . local_map . get ( temp) {
141
+ for & borrow_index in borrow_indices {
142
+ let location_index = self . location_table . mid_index ( location) ;
143
+ all_facts. killed . push ( ( borrow_index, location_index) ) ;
144
+ }
145
+ }
146
+ }
147
+ }
148
+
149
+ self . super_assign ( block, place, rvalue, location) ;
150
+ }
151
+
152
+ fn visit_terminator (
153
+ & mut self ,
154
+ block : BasicBlock ,
155
+ terminator : & Terminator < ' tcx > ,
156
+ location : Location ,
157
+ ) {
158
+ if let Some ( all_facts) = self . all_facts {
159
+ all_facts. cfg_edge . push ( (
160
+ self . location_table . start_index ( location) ,
161
+ self . location_table . mid_index ( location) ,
162
+ ) ) ;
163
+
164
+ for successor_block in terminator. successors ( ) {
165
+ all_facts. cfg_edge . push ( (
166
+ self . location_table . mid_index ( location) ,
167
+ self . location_table
168
+ . start_index ( successor_block. start_location ( ) ) ,
169
+ ) ) ;
170
+ }
171
+ }
172
+
173
+ self . super_terminator ( block, terminator, location) ;
174
+ }
175
+
93
176
fn visit_rvalue ( & mut self , rvalue : & Rvalue < ' tcx > , location : Location ) {
94
177
debug ! ( "visit_rvalue(rvalue={:?}, location={:?})" , rvalue, location) ;
95
178
96
- // Look for an rvalue like:
97
- //
98
- // & L
99
- //
100
- // where L is the path that is borrowed. In that case, we have
101
- // to add the reborrow constraints (which don't fall out
102
- // naturally from the type-checker).
103
- if let Rvalue :: Ref ( region, _bk, ref borrowed_lv) = * rvalue {
104
- self . add_reborrow_constraint ( location, region, borrowed_lv) ;
179
+ match rvalue {
180
+ Rvalue :: Ref ( region, _borrow_kind, borrowed_place) => {
181
+ // In some cases, e.g. when borrowing from an unsafe
182
+ // place, we don't bother to create a loan, since
183
+ // there are no conditions to validate.
184
+ if let Some ( all_facts) = self . all_facts {
185
+ if let Some ( borrow_index) = self . borrow_set . location_map . get ( & location) {
186
+ let region_vid = region. to_region_vid ( ) ;
187
+ all_facts. borrow_region . push ( (
188
+ region_vid,
189
+ * borrow_index,
190
+ self . location_table . mid_index ( location) ,
191
+ ) ) ;
192
+ }
193
+ }
194
+
195
+ // Look for an rvalue like:
196
+ //
197
+ // & L
198
+ //
199
+ // where L is the path that is borrowed. In that case, we have
200
+ // to add the reborrow constraints (which don't fall out
201
+ // naturally from the type-checker).
202
+ self . add_reborrow_constraint ( location, region, borrowed_place) ;
203
+ }
204
+
205
+ _ => { }
105
206
}
106
207
107
208
self . super_rvalue ( rvalue, location) ;
108
209
}
109
210
110
- fn visit_user_assert_ty ( & mut self , _c_ty : & CanonicalTy < ' tcx > ,
111
- _local : & Local , _location : Location ) { }
211
+ fn visit_user_assert_ty (
212
+ & mut self ,
213
+ _c_ty : & CanonicalTy < ' tcx > ,
214
+ _local : & Local ,
215
+ _location : Location ,
216
+ ) {
217
+ }
112
218
}
113
219
114
220
impl < ' cx , ' cg , ' gcx , ' tcx > ConstraintGeneration < ' cx , ' cg , ' gcx , ' tcx > {
@@ -122,8 +228,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
122
228
{
123
229
debug ! (
124
230
"add_regular_live_constraint(live_ty={:?}, location={:?})" ,
125
- live_ty,
126
- location
231
+ live_ty, location
127
232
) ;
128
233
129
234
self . infcx
@@ -144,8 +249,10 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
144
249
) {
145
250
let mut borrowed_place = borrowed_place;
146
251
147
- debug ! ( "add_reborrow_constraint({:?}, {:?}, {:?})" ,
148
- location, borrow_region, borrowed_place) ;
252
+ debug ! (
253
+ "add_reborrow_constraint({:?}, {:?}, {:?})" ,
254
+ location, borrow_region, borrowed_place
255
+ ) ;
149
256
while let Projection ( box PlaceProjection { base, elem } ) = borrowed_place {
150
257
debug ! ( "add_reborrow_constraint - iteration {:?}" , borrowed_place) ;
151
258
@@ -165,12 +272,20 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
165
272
location. successor_within_block ( ) ,
166
273
) ;
167
274
275
+ if let Some ( all_facts) = self . all_facts {
276
+ all_facts. outlives . push ( (
277
+ ref_region. to_region_vid ( ) ,
278
+ borrow_region. to_region_vid ( ) ,
279
+ self . location_table . mid_index ( location) ,
280
+ ) ) ;
281
+ }
282
+
168
283
match mutbl {
169
284
hir:: Mutability :: MutImmutable => {
170
285
// Immutable reference. We don't need the base
171
286
// to be valid for the entire lifetime of
172
287
// the borrow.
173
- break
288
+ break ;
174
289
}
175
290
hir:: Mutability :: MutMutable => {
176
291
// Mutable reference. We *do* need the base
@@ -199,19 +314,19 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
199
314
}
200
315
ty:: TyRawPtr ( ..) => {
201
316
// deref of raw pointer, guaranteed to be valid
202
- break
317
+ break ;
203
318
}
204
319
ty:: TyAdt ( def, _) if def. is_box ( ) => {
205
320
// deref of `Box`, need the base to be valid - propagate
206
321
}
207
- _ => bug ! ( "unexpected deref ty {:?} in {:?}" , base_ty, borrowed_place)
322
+ _ => bug ! ( "unexpected deref ty {:?} in {:?}" , base_ty, borrowed_place) ,
208
323
}
209
324
}
210
- ProjectionElem :: Field ( ..) |
211
- ProjectionElem :: Downcast ( ..) |
212
- ProjectionElem :: Index ( ..) |
213
- ProjectionElem :: ConstantIndex { .. } |
214
- ProjectionElem :: Subslice { .. } => {
325
+ ProjectionElem :: Field ( ..)
326
+ | ProjectionElem :: Downcast ( ..)
327
+ | ProjectionElem :: Index ( ..)
328
+ | ProjectionElem :: ConstantIndex { .. }
329
+ | ProjectionElem :: Subslice { .. } => {
215
330
// other field access
216
331
}
217
332
}
0 commit comments