@@ -292,32 +292,21 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
292
292
location : Location ,
293
293
is_activations : bool ) {
294
294
if let Some ( ref regioncx) = self . nonlexical_regioncx {
295
+ // NOTE: The state associated with a given `location`
296
+ // reflects the dataflow on entry to the statement. If it
297
+ // does not contain `borrow_region`, then then that means
298
+ // that the statement at `location` kills the borrow.
299
+ //
300
+ // We are careful always to call this function *before* we
301
+ // set up the gen-bits for the statement or
302
+ // termanator. That way, if the effect of the statement or
303
+ // terminator *does* introduce a new loan of the same
304
+ // region, then setting that gen-bit will override any
305
+ // potential kill introduced here.
295
306
for ( borrow_index, borrow_data) in self . borrows . iter_enumerated ( ) {
296
307
let borrow_region = borrow_data. region . to_region_vid ( ) ;
297
308
if !regioncx. region_contains_point ( borrow_region, location) {
298
- // The region checker really considers the borrow
299
- // to start at the point **after** the location of
300
- // the borrow, but the borrow checker puts the gen
301
- // directly **on** the location of the
302
- // borrow. This results in a gen/kill both being
303
- // generated for same point if we are not
304
- // careful. Probably we should change the point of
305
- // the gen, but for now we hackily account for the
306
- // mismatch here by not generating a kill for the
307
- // location on the borrow itself.
308
- if location != borrow_data. location {
309
- sets. kill ( & ReserveOrActivateIndex :: reserved ( borrow_index) ) ;
310
- }
311
-
312
- // FIXME: the logic used to justify the above
313
- // "accounting for mismatch" does not generalize
314
- // to activations, so we set the kill-bits without
315
- // that same location check here.
316
- //
317
- // But... can we get into a situation where the
318
- // gen/kill bits are both sets in this case, in
319
- // which case we *do* need an analogous guard of
320
- // some kind?
309
+ sets. kill ( & ReserveOrActivateIndex :: reserved ( borrow_index) ) ;
321
310
if is_activations {
322
311
sets. kill ( & ReserveOrActivateIndex :: active ( borrow_index) ) ;
323
312
}
@@ -340,14 +329,18 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
340
329
panic ! ( "could not find statement at location {:?}" ) ;
341
330
} ) ;
342
331
332
+ // Do kills introduced by NLL before setting up any potential
333
+ // gens. (See NOTE in kill_loans_out_of_scope_at_location.)
334
+ self . kill_loans_out_of_scope_at_location ( sets, location, is_activations) ;
335
+
343
336
if is_activations {
344
- // INVARIANT: At this point, `sets.on_entry` should
345
- // correctly reflect the reservations as we enter the
346
- // statement (because accumulates_intrablock_state is
347
- // overridden)
337
+ // INVARIANT: `sets.on_entry` accurately captures
338
+ // reservations on entry to statement (b/c
339
+ // accumulates_intrablock_state is overridden for
340
+ // ActiveBorrows).
348
341
//
349
- // Now compute effect of the statement on the activations
350
- // themselves in the ActiveBorrows state.
342
+ // Now compute the activations generated by uses within
343
+ // the statement based on that reservation state.
351
344
let mut find = FindPlaceUses { sets, assigned_map : & self . assigned_map } ;
352
345
find. visit_statement ( location. block , stmt, location) ;
353
346
}
@@ -414,8 +407,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
414
407
mir:: StatementKind :: Nop => { }
415
408
416
409
}
417
-
418
- self . kill_loans_out_of_scope_at_location ( sets, location, is_activations) ;
419
410
}
420
411
421
412
/// Models terminator effect in Reservations and ActiveBorrows
@@ -429,9 +420,19 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
429
420
panic ! ( "could not find block at location {:?}" , location) ;
430
421
} ) ;
431
422
423
+ // Do kills introduced by NLL before setting up any potential
424
+ // gens. (See NOTE in kill_loans_out_of_scope_at_location.)
425
+ self . kill_loans_out_of_scope_at_location ( sets, location, is_activations) ;
426
+
432
427
let term = block. terminator ( ) ;
433
428
if is_activations {
434
- // Any uses of reserved Places in the statement are now activated.
429
+ // INVARIANT: `sets.on_entry` accurately captures
430
+ // reservations on entry to terminator (b/c
431
+ // accumulates_intrablock_state is overridden for
432
+ // ActiveBorrows).
433
+ //
434
+ // Now compute effect of the terminator on the activations
435
+ // themselves in the ActiveBorrows state.
435
436
let mut find = FindPlaceUses { sets, assigned_map : & self . assigned_map } ;
436
437
find. visit_terminator ( location. block , term, location) ;
437
438
}
@@ -474,7 +475,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
474
475
mir:: TerminatorKind :: FalseEdges { ..} |
475
476
mir:: TerminatorKind :: Unreachable => { }
476
477
}
477
- self . kill_loans_out_of_scope_at_location ( sets, location, is_activations) ;
478
478
}
479
479
}
480
480
0 commit comments