Distinguish borrows of copies from other borrows

This commit is contained in:
Eric Holk 2022-02-23 15:46:09 -08:00
parent ac804f27a8
commit 87ad6683d6
2 changed files with 34 additions and 7 deletions

View file

@ -114,15 +114,31 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
.borrowed
.insert(TrackedValue::from_place_with_projections_allowed(place_with_id));
// XXX -- we need to distinguish "consuming a copy" from other borrows
// Keep track of whether this is a borrowed temporary (i.e. a borrow of an RValue)
// so that later in generator_interior we can use the correct scope.
//
// XXX -- we need to distinguish `&*E` where `E: &T` which is not creating a temporary
// even though the place-base E is an rvalue
// We ignore borrows that are the result of an autoref because these will be
// immediately consumed and should not extend the temporary's lifetime.
if let (false, PlaceBase::Rvalue) = (is_autoref, place_with_id.place.base) {
self.places.borrowed_temporaries.insert(place_with_id.hir_id);
}
}
fn copy(
&mut self,
place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>,
_diag_expr_id: HirId,
) {
debug!("copy: place_with_id = {place_with_id:?}");
self.places
.borrowed
.insert(TrackedValue::from_place_with_projections_allowed(place_with_id));
// For copied we treat this mostly like a borrow except that we don't add the place
// to borrowed_temporaries because the copy is consumed.
}
fn mutate(
&mut self,
assignee_place: &expr_use_visitor::PlaceWithHirId<'tcx>,

View file

@ -48,6 +48,14 @@ pub trait Delegate<'tcx> {
is_autoref: bool,
);
/// The value found at `place` is being copied.
/// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
fn copy(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId) {
// In most cases, treating a copy as a borrow is the right thing, so we forward
// this to the borrow callback by default.
self.borrow(place_with_id, diag_expr_id, ty::BorrowKind::ImmBorrow, false)
}
/// 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);
@ -598,7 +606,12 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
adjustment::AutoBorrow::RawPtr(m) => {
debug!("walk_autoref: expr.hir_id={} base_place={:?}", expr.hir_id, base_place);
self.delegate.borrow(base_place, base_place.hir_id, ty::BorrowKind::from_mutbl(m), true);
self.delegate.borrow(
base_place,
base_place.hir_id,
ty::BorrowKind::from_mutbl(m),
true,
);
}
}
}
@ -839,9 +852,7 @@ fn delegate_consume<'a, 'tcx>(
match mode {
ConsumeMode::Move => delegate.consume(place_with_id, diag_expr_id),
ConsumeMode::Copy => {
delegate.borrow(place_with_id, diag_expr_id, ty::BorrowKind::ImmBorrow, false)
}
ConsumeMode::Copy => delegate.copy(place_with_id, diag_expr_id),
}
}