about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs18
-rw-r--r--compiler/rustc_typeck/src/expr_use_visitor.rs6
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 03d3b23bb23..f2907bb2634 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 db1c80ae433..9f450270941 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);