From 3f73491589d99ad60d785add0309637423fe7368 Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Mon, 28 Feb 2022 12:54:07 -0800 Subject: [PATCH] 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. --- .../drop_ranges/record_consumed_borrow.rs | 18 +++++++++++++----- compiler/rustc_typeck/src/expr_use_visitor.rs | 6 +++++- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs index 03d3b23bb23d..f2907bb2634a 100644 --- a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs +++ b/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs @@ -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( diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index db1c80ae433b..9f4502709418 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -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);