about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/dataflow/impls/borrows.rs66
1 files changed, 33 insertions, 33 deletions
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index 4c36deae101..c61a57cdda0 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -292,32 +292,21 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
                                            location: Location,
                                            is_activations: bool) {
         if let Some(ref regioncx) = self.nonlexical_regioncx {
+            // NOTE: The state associated with a given `location`
+            // reflects the dataflow on entry to the statement. If it
+            // does not contain `borrow_region`, then then that means
+            // that the statement at `location` kills the borrow.
+            //
+            // We are careful always to call this function *before* we
+            // set up the gen-bits for the statement or
+            // termanator. That way, if the effect of the statement or
+            // terminator *does* introduce a new loan of the same
+            // region, then setting that gen-bit will override any
+            // potential kill introduced here.
             for (borrow_index, borrow_data) in self.borrows.iter_enumerated() {
                 let borrow_region = borrow_data.region.to_region_vid();
                 if !regioncx.region_contains_point(borrow_region, location) {
-                    // The region checker really considers the borrow
-                    // to start at the point **after** the location of
-                    // the borrow, but the borrow checker puts the gen
-                    // directly **on** the location of the
-                    // borrow. This results in a gen/kill both being
-                    // generated for same point if we are not
-                    // careful. Probably we should change the point of
-                    // the gen, but for now we hackily account for the
-                    // mismatch here by not generating a kill for the
-                    // location on the borrow itself.
-                    if location != borrow_data.location {
-                        sets.kill(&ReserveOrActivateIndex::reserved(borrow_index));
-                    }
-
-                    // FIXME: the logic used to justify the above
-                    // "accounting for mismatch" does not generalize
-                    // to activations, so we set the kill-bits without
-                    // that same location check here.
-                    //
-                    // But... can we get into a situation where the
-                    // gen/kill bits are both sets in this case, in
-                    // which case we *do* need an analogous guard of
-                    // some kind?
+                    sets.kill(&ReserveOrActivateIndex::reserved(borrow_index));
                     if is_activations {
                         sets.kill(&ReserveOrActivateIndex::active(borrow_index));
                     }
@@ -340,14 +329,18 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
             panic!("could not find statement at location {:?}");
         });
 
+        // Do kills introduced by NLL before setting up any potential
+        // gens. (See NOTE in kill_loans_out_of_scope_at_location.)
+        self.kill_loans_out_of_scope_at_location(sets, location, is_activations);
+
         if is_activations {
-            // INVARIANT: At this point, `sets.on_entry` should
-            // correctly reflect the reservations as we enter the
-            // statement (because accumulates_intrablock_state is
-            // overridden)
+            // INVARIANT: `sets.on_entry` accurately captures
+            // reservations on entry to statement (b/c
+            // accumulates_intrablock_state is overridden for
+            // ActiveBorrows).
             //
-            // Now compute effect of the statement on the activations
-            // themselves in the ActiveBorrows state.
+            // Now compute the activations generated by uses within
+            // the statement based on that reservation state.
             let mut find = FindPlaceUses { sets, assigned_map: &self.assigned_map };
             find.visit_statement(location.block, stmt, location);
         }
@@ -414,8 +407,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
             mir::StatementKind::Nop => {}
 
         }
-
-        self.kill_loans_out_of_scope_at_location(sets, location, is_activations);
     }
 
     /// Models terminator effect in Reservations and ActiveBorrows
@@ -429,9 +420,19 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
             panic!("could not find block at location {:?}", location);
         });
 
+        // Do kills introduced by NLL before setting up any potential
+        // gens. (See NOTE in kill_loans_out_of_scope_at_location.)
+        self.kill_loans_out_of_scope_at_location(sets, location, is_activations);
+
         let term = block.terminator();
         if is_activations {
-            // Any uses of reserved Places in the statement are now activated.
+            // INVARIANT: `sets.on_entry` accurately captures
+            // reservations on entry to terminator (b/c
+            // accumulates_intrablock_state is overridden for
+            // ActiveBorrows).
+            //
+            // Now compute effect of the terminator on the activations
+            // themselves in the ActiveBorrows state.
             let mut find = FindPlaceUses { sets, assigned_map: &self.assigned_map };
             find.visit_terminator(location.block, term, location);
         }
@@ -474,7 +475,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
             mir::TerminatorKind::FalseEdges {..} |
             mir::TerminatorKind::Unreachable => {}
         }
-        self.kill_loans_out_of_scope_at_location(sets, location, is_activations);
     }
 }