After discussion with ariel, replacing a guard within kill_loans_out_of_scope_at_location.

Instead we are "just" careful to invoke it (which sets up a bunch of kill bits)
before we go into the code that sets up the gen bits.

That way, when the gen bits are set up, they will override any
previously set kill-bits for those reservations or activations.
This commit is contained in:
Felix S. Klock II 2017-12-13 18:10:37 -06:00
parent 3c7d9ff90a
commit f96777c9ff

View file

@ -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);
}
}