Skip to content

Commit 3f73491

Browse files
committed
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.
1 parent 97cde9f commit 3f73491

File tree

2 files changed

+18
-6
lines changed

2 files changed

+18
-6
lines changed

compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,19 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
107107
assignee_place: &expr_use_visitor::PlaceWithHirId<'tcx>,
108108
diag_expr_id: HirId,
109109
) {
110-
debug!("mutate {:?}; diag_expr_id={:?}", assignee_place, diag_expr_id);
111-
// Count mutations as a borrow.
112-
self.places
113-
.borrowed
114-
.insert(TrackedValue::from_place_with_projections_allowed(assignee_place));
110+
debug!("mutate {assignee_place:?}; diag_expr_id={diag_expr_id:?}");
111+
// Count mutations as a borrow when done through a projection.
112+
//
113+
// The goal here is to catch cases such as `x.y = 42`, since MIR will count this
114+
// as a borrow of `x`, and we need to match that behavior.
115+
//
116+
// FIXME(eholk): this is probably still more conservative than we need to be. For example,
117+
// we may need to count `*x = 42` as a borrow of `x`, since it overwrites all of `x`.
118+
if !assignee_place.place.projections.is_empty() {
119+
self.places
120+
.borrowed
121+
.insert(TrackedValue::from_place_with_projections_allowed(assignee_place));
122+
}
115123
}
116124

117125
fn fake_read(

compiler/rustc_typeck/src/expr_use_visitor.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ pub trait Delegate<'tcx> {
4949

5050
/// The path at `assignee_place` is being assigned to.
5151
/// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
52-
fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId);
52+
fn mutate(
53+
&mut self,
54+
assignee_place: &PlaceWithHirId<'tcx>,
55+
diag_expr_id: hir::HirId
56+
);
5357

5458
/// The `place` should be a fake read because of specified `cause`.
5559
fn fake_read(&mut self, place: Place<'tcx>, cause: FakeReadCause, diag_expr_id: hir::HirId);

0 commit comments

Comments
 (0)