From 1702c000562b914e926e4b586f1fb4a6945ab345 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 21 Feb 2025 18:27:58 -0300 Subject: [PATCH] Make captures in ByUse context be always ty::UpvarCapture::ByUse --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 27 ++++++++++++------- compiler/rustc_hir_typeck/src/upvar.rs | 23 +++++++++++----- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 4b6174769ea6..e7e648dc26b0 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -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, diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 40a935afbac2..f570d0d8a0d3 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -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: