Make captures in ByUse context be always ty::UpvarCapture::ByUse

This commit is contained in:
Santiago Pastorino 2025-02-21 18:27:58 -03:00
parent 65d65e5e7e
commit 1702c00056
No known key found for this signature in database
GPG key ID: 8131A24E0C79EFAF
2 changed files with 33 additions and 17 deletions

View file

@ -324,6 +324,18 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
}
}
pub fn consume_clone_or_copy(&self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
debug!("delegate_consume_or_clone(place_with_id={:?})", place_with_id);
if self.cx.type_is_copy_modulo_regions(place_with_id.place.ty()) {
self.delegate.borrow_mut().copy(place_with_id, diag_expr_id);
} else if self.cx.type_is_use_cloned_modulo_regions(place_with_id.place.ty()) {
self.delegate.borrow_mut().use_cloned(place_with_id, diag_expr_id);
} else {
self.delegate.borrow_mut().consume(place_with_id, diag_expr_id);
}
}
fn consume_exprs(&self, exprs: &[hir::Expr<'_>]) -> Result<(), Cx::Error> {
for expr in exprs {
self.consume_expr(expr)?;
@ -346,15 +358,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
debug!("consume_or_clone_expr(expr={:?})", expr);
let place_with_id = self.cat_expr(expr)?;
if self.cx.type_is_copy_modulo_regions(place_with_id.place.ty()) {
self.delegate.borrow_mut().copy(&place_with_id, place_with_id.hir_id);
} else if self.cx.type_is_use_cloned_modulo_regions(place_with_id.place.ty()) {
self.delegate.borrow_mut().use_cloned(&place_with_id, place_with_id.hir_id);
} else {
self.delegate.borrow_mut().consume(&place_with_id, place_with_id.hir_id);
}
self.consume_clone_or_copy(&place_with_id, place_with_id.hir_id);
self.walk_expr(expr)?;
Ok(())
}
@ -1132,9 +1136,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
);
match capture_info.capture_kind {
ty::UpvarCapture::ByValue | ty::UpvarCapture::ByUse => {
ty::UpvarCapture::ByValue => {
self.consume_or_copy(&place_with_id, place_with_id.hir_id);
}
ty::UpvarCapture::ByUse => {
self.consume_clone_or_copy(&place_with_id, place_with_id.hir_id);
}
ty::UpvarCapture::ByRef(upvar_borrow) => {
self.delegate.borrow_mut().borrow(
&place_with_id,

View file

@ -1709,11 +1709,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Otherwise you'd get an error in 2021 immediately because you'd be trying to take
// ownership of the (borrowed) String or else you'd take ownership of b, as in 2018 and
// before, which is also an error.
hir::CaptureBy::Value { .. } | hir::CaptureBy::Use { .. }
if !place.deref_tys().any(Ty::is_ref) =>
{
hir::CaptureBy::Value { .. } if !place.deref_tys().any(Ty::is_ref) => {
ty::UpvarCapture::ByValue
}
hir::CaptureBy::Use { .. } if !place.deref_tys().any(Ty::is_ref) => {
ty::UpvarCapture::ByUse
}
hir::CaptureBy::Value { .. } | hir::CaptureBy::Use { .. } | hir::CaptureBy::Ref => {
ty::UpvarCapture::ByRef(BorrowKind::Immutable)
}
@ -2404,10 +2405,18 @@ fn determine_capture_info(
// We select the CaptureKind which ranks higher based the following priority order:
// (ByUse | ByValue) > MutBorrow > UniqueImmBorrow > ImmBorrow
match (capture_info_a.capture_kind, capture_info_b.capture_kind) {
(ty::UpvarCapture::ByUse, _) => capture_info_a,
(_, ty::UpvarCapture::ByUse) => capture_info_b,
(ty::UpvarCapture::ByValue, _) => capture_info_a,
(_, ty::UpvarCapture::ByValue) => capture_info_b,
(ty::UpvarCapture::ByUse, ty::UpvarCapture::ByValue)
| (ty::UpvarCapture::ByValue, ty::UpvarCapture::ByUse) => {
bug!("Same capture can't be ByUse and ByValue at the same time")
}
(ty::UpvarCapture::ByValue, ty::UpvarCapture::ByValue)
| (ty::UpvarCapture::ByUse, ty::UpvarCapture::ByUse)
| (ty::UpvarCapture::ByValue | ty::UpvarCapture::ByUse, ty::UpvarCapture::ByRef(_)) => {
capture_info_a
}
(ty::UpvarCapture::ByRef(_), ty::UpvarCapture::ByValue | ty::UpvarCapture::ByUse) => {
capture_info_b
}
(ty::UpvarCapture::ByRef(ref_a), ty::UpvarCapture::ByRef(ref_b)) => {
match (ref_a, ref_b) {
// Take LHS: