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 3ff7d7ad010..b07e3a18e3f 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 @@ -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>, diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index 1cce2a1da74..b15f7cf2889 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -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), } }