@@ -3,12 +3,15 @@ use crate::borrow_check::location::LocationTable;
3
3
use crate :: borrow_check:: nll:: ToRegionVid ;
4
4
use crate :: borrow_check:: nll:: facts:: AllFacts ;
5
5
use crate :: borrow_check:: nll:: region_infer:: values:: LivenessValues ;
6
+ use crate :: borrow_check:: places_conflict;
6
7
use rustc:: infer:: InferCtxt ;
7
8
use rustc:: mir:: visit:: TyContext ;
8
9
use rustc:: mir:: visit:: Visitor ;
9
- use rustc:: mir:: { BasicBlock , BasicBlockData , Location , Body , Place , PlaceBase , Rvalue , TerminatorKind } ;
10
- use rustc:: mir:: { Local , SourceInfo , Statement , StatementKind , Terminator } ;
11
- use rustc:: mir:: UserTypeProjection ;
10
+ use rustc:: mir:: {
11
+ BasicBlock , BasicBlockData , Body , Local , Location , Place , PlaceBase , Projection ,
12
+ ProjectionElem , Rvalue , SourceInfo , Statement , StatementKind , Terminator , TerminatorKind ,
13
+ UserTypeProjection ,
14
+ } ;
12
15
use rustc:: ty:: fold:: TypeFoldable ;
13
16
use rustc:: ty:: { self , ClosureSubsts , GeneratorSubsts , RegionVid , Ty } ;
14
17
use rustc:: ty:: subst:: SubstsRef ;
@@ -27,6 +30,7 @@ pub(super) fn generate_constraints<'cx, 'tcx>(
27
30
liveness_constraints,
28
31
location_table,
29
32
all_facts,
33
+ body,
30
34
} ;
31
35
32
36
for ( bb, data) in body. basic_blocks ( ) . iter_enumerated ( ) {
@@ -41,6 +45,7 @@ struct ConstraintGeneration<'cg, 'cx, 'tcx> {
41
45
location_table : & ' cg LocationTable ,
42
46
liveness_constraints : & ' cg mut LivenessValues < RegionVid > ,
43
47
borrow_set : & ' cg BorrowSet < ' tcx > ,
48
+ body : & ' cg Body < ' tcx > ,
44
49
}
45
50
46
51
impl < ' cg , ' cx , ' tcx > Visitor < ' tcx > for ConstraintGeneration < ' cg , ' cx , ' tcx > {
@@ -212,17 +217,73 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> {
212
217
/// as `killed`. For example, when assigning to a local, or on a call's return destination.
213
218
fn record_killed_borrows_for_place ( & mut self , place : & Place < ' tcx > , location : Location ) {
214
219
if let Some ( all_facts) = self . all_facts {
215
- if let Place {
216
- base : PlaceBase :: Local ( local) ,
217
- projection : None ,
218
- } = place {
219
- record_killed_borrows_for_local (
220
- all_facts,
221
- self . borrow_set ,
222
- self . location_table ,
223
- local,
224
- location,
225
- ) ;
220
+ // Depending on the `Place` we're killing:
221
+ // - if it's a local, or a single deref of a local,
222
+ // we kill all the borrows on the local.
223
+ // - if it's a deeper projection, we have to filter which
224
+ // of the borrows are killed: the ones whose `borrowed_place`
225
+ // conflicts with the `place`.
226
+ match place {
227
+ Place {
228
+ base : PlaceBase :: Local ( local) ,
229
+ projection : None ,
230
+ } |
231
+ Place {
232
+ base : PlaceBase :: Local ( local) ,
233
+ projection : Some ( box Projection {
234
+ base : None ,
235
+ elem : ProjectionElem :: Deref ,
236
+ } ) ,
237
+ } => {
238
+ debug ! (
239
+ "Recording `killed` facts for borrows of local={:?} at location={:?}" ,
240
+ local, location
241
+ ) ;
242
+
243
+ record_killed_borrows_for_local (
244
+ all_facts,
245
+ self . borrow_set ,
246
+ self . location_table ,
247
+ local,
248
+ location,
249
+ ) ;
250
+ }
251
+
252
+ Place {
253
+ base : PlaceBase :: Static ( _) ,
254
+ ..
255
+ } => {
256
+ // Ignore kills of static or static mut variables.
257
+ }
258
+
259
+ Place {
260
+ base : PlaceBase :: Local ( local) ,
261
+ projection : Some ( _) ,
262
+ } => {
263
+ // Kill conflicting borrows of the innermost local.
264
+ debug ! (
265
+ "Recording `killed` facts for borrows of \
266
+ innermost projected local={:?} at location={:?}",
267
+ local, location
268
+ ) ;
269
+
270
+ if let Some ( borrow_indices) = self . borrow_set . local_map . get ( local) {
271
+ for & borrow_index in borrow_indices {
272
+ let places_conflict = places_conflict:: places_conflict (
273
+ self . infcx . tcx ,
274
+ self . body ,
275
+ & self . borrow_set . borrows [ borrow_index] . borrowed_place ,
276
+ place,
277
+ places_conflict:: PlaceConflictBias :: NoOverlap ,
278
+ ) ;
279
+
280
+ if places_conflict {
281
+ let location_index = self . location_table . mid_index ( location) ;
282
+ all_facts. killed . push ( ( borrow_index, location_index) ) ;
283
+ }
284
+ }
285
+ }
286
+ }
226
287
}
227
288
}
228
289
}
0 commit comments