Only count mutations with projections as borrows

Because bindings also count as a mutation, the previous behavior counted
all variables as borrowed, completely negating the effect of drop
tracking.
This commit is contained in:
Eric Holk 2022-02-28 12:54:07 -08:00
parent 97cde9fe08
commit 3f73491589
2 changed files with 18 additions and 6 deletions

View file

@ -107,11 +107,19 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
assignee_place: &expr_use_visitor::PlaceWithHirId<'tcx>,
diag_expr_id: HirId,
) {
debug!("mutate {:?}; diag_expr_id={:?}", assignee_place, diag_expr_id);
// Count mutations as a borrow.
self.places
.borrowed
.insert(TrackedValue::from_place_with_projections_allowed(assignee_place));
debug!("mutate {assignee_place:?}; diag_expr_id={diag_expr_id:?}");
// Count mutations as a borrow when done through a projection.
//
// The goal here is to catch cases such as `x.y = 42`, since MIR will count this
// as a borrow of `x`, and we need to match that behavior.
//
// FIXME(eholk): this is probably still more conservative than we need to be. For example,
// we may need to count `*x = 42` as a borrow of `x`, since it overwrites all of `x`.
if !assignee_place.place.projections.is_empty() {
self.places
.borrowed
.insert(TrackedValue::from_place_with_projections_allowed(assignee_place));
}
}
fn fake_read(

View file

@ -49,7 +49,11 @@ pub trait Delegate<'tcx> {
/// The path at `assignee_place` is being assigned to.
/// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId);
fn mutate(
&mut self,
assignee_place: &PlaceWithHirId<'tcx>,
diag_expr_id: hir::HirId
);
/// The `place` should be a fake read because of specified `cause`.
fn fake_read(&mut self, place: Place<'tcx>, cause: FakeReadCause, diag_expr_id: hir::HirId);