From fc7fe91ee55805c06a5ffed50c6a7fe6e39a5f6f Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Tue, 29 Sep 2026 11:55:02 -0400 Subject: [PATCH 1/5] Reborrow `&mut` on every move --- .../src/builder/expr/as_rvalue.rs | 2 +- .../rustc_mir_build/src/builder/expr/into.rs | 26 +- .../src/builder/matches/mod.rs | 7 +- compiler/rustc_mir_build/src/builder/misc.rs | 25 +- .../reborrow.remut.CopyProp.panic-unwind.diff | 27 +- .../reborrow.reraw.CopyProp.panic-unwind.diff | 27 +- .../gvn.references.GVN.panic-unwind.diff | 72 +++-- ...lice_get.LowerIntrinsics.panic-unwind.diff | 56 ++-- ..._propagation_mut.ReferencePropagation.diff | 301 +++++++++--------- ...rrowck-for-loop-correct-cmt-for-pattern.rs | 2 +- ...ck-for-loop-correct-cmt-for-pattern.stderr | 17 +- tests/ui/borrowck/borrowck-issue-48962.rs | 24 +- tests/ui/borrowck/borrowck-issue-48962.stderr | 23 -- .../ui/borrowck/borrowck-move-mut-base-ptr.rs | 2 +- .../borrowck-move-mut-base-ptr.stderr | 18 +- ...n-closure-move-capture-no-reborrow-sugg.rs | 6 +- ...osure-move-capture-no-reborrow-sugg.stderr | 57 +--- tests/ui/borrowck/issue-101119.rs | 9 +- tests/ui/borrowck/issue-101119.stderr | 24 -- tests/ui/borrowck/issue-83924.fixed | 20 -- tests/ui/borrowck/issue-83924.rs | 3 +- tests/ui/borrowck/issue-83924.stderr | 22 -- .../borrowck/move-in-pattern-mut-in-loop.rs | 7 +- .../move-in-pattern-mut-in-loop.stderr | 15 - ...-value-suggest-reborrow-issue-127285.fixed | 17 - ...ved-value-suggest-reborrow-issue-127285.rs | 3 +- ...value-suggest-reborrow-issue-127285.stderr | 18 -- tests/ui/borrowck/mut-autoreborrow.rs | 44 +++ tests/ui/borrowck/mut-borrow-in-loop-2.rs | 4 +- tests/ui/borrowck/mut-borrow-in-loop-2.stderr | 18 -- .../reborrow-sugg-move-then-borrow.rs | 13 +- .../reborrow-sugg-move-then-borrow.stderr | 21 -- .../closures/mut-autoreborrow-closure-2024.rs | 9 + .../mut-autoreborrow-closure-cursed-fail.rs | 19 ++ ...ut-autoreborrow-closure-cursed-fail.stderr | 14 + .../mut-autoreborrow-closure-cursed.rs | 19 ++ .../closures/mut-autoreborrow-closure-fail.rs | 15 + .../mut-autoreborrow-closure-fail.stderr | 23 ++ .../closures/mut-autoreborrow-closure-win.rs | 12 + tests/ui/mir-dataflow/inits-1.rs | 4 +- tests/ui/mir-dataflow/inits-1.stderr | 8 +- tests/ui/mir-dataflow/uninits-1.rs | 6 +- tests/ui/mir-dataflow/uninits-1.stderr | 8 +- tests/ui/mir-dataflow/uninits-2.rs | 4 +- tests/ui/mir-dataflow/uninits-2.stderr | 8 +- tests/ui/nll/closure-access-spans.rs | 4 +- tests/ui/nll/closure-access-spans.stderr | 26 +- tests/ui/nll/closure-borrow-spans.stderr | 10 +- ...issue-27282-move-match-input-into-guard.rs | 24 +- ...e-27282-move-match-input-into-guard.stderr | 36 +-- .../issue-27282-move-ref-mut-into-guard.rs | 4 +- ...issue-27282-move-ref-mut-into-guard.stderr | 18 +- tests/ui/nll/issue-27282-mutation-in-guard.rs | 4 +- .../nll/issue-27282-mutation-in-guard.stderr | 18 +- ...59-report-when-borrow-and-drop-conflict.rs | 2 +- ...eport-when-borrow-and-drop-conflict.stderr | 19 +- tests/ui/nll/match-guards-always-borrow.rs | 4 +- .../ui/nll/match-guards-always-borrow.stderr | 18 +- .../nll-problem-case-3-issue-68934.nll.stderr | 10 +- .../polonius-smoke-test.legacy.stderr | 36 +-- .../polonius-smoke-test.polonius.stderr | 36 +-- .../borrowck-pat-ref-mut-and-ref.rs | 6 +- .../borrowck-pat-ref-mut-and-ref.stderr | 54 ++-- .../borrowck-errors.classic2021.stderr | 23 +- .../borrowck-errors.classic2024.stderr | 64 +--- .../experimental/borrowck-errors.rs | 6 +- .../borrowck-errors.stable2021.stderr | 22 +- .../borrowck-errors.structural2021.stderr | 19 +- .../borrowck-errors.structural2024.stderr | 19 +- tests/ui/reborrow/mut-autoreborrow-fail.rs | 14 + .../ui/reborrow/mut-autoreborrow-fail.stderr | 23 ++ tests/ui/try-block/try-block-bad-lifetime.rs | 2 +- .../try-block/try-block-bad-lifetime.stderr | 16 +- 73 files changed, 754 insertions(+), 862 deletions(-) delete mode 100644 tests/ui/borrowck/borrowck-issue-48962.stderr delete mode 100644 tests/ui/borrowck/issue-101119.stderr delete mode 100644 tests/ui/borrowck/issue-83924.fixed delete mode 100644 tests/ui/borrowck/issue-83924.stderr delete mode 100644 tests/ui/borrowck/move-in-pattern-mut-in-loop.stderr delete mode 100644 tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.fixed delete mode 100644 tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.stderr create mode 100644 tests/ui/borrowck/mut-autoreborrow.rs delete mode 100644 tests/ui/borrowck/mut-borrow-in-loop-2.stderr delete mode 100644 tests/ui/borrowck/reborrow-sugg-move-then-borrow.stderr create mode 100644 tests/ui/closures/mut-autoreborrow-closure-2024.rs create mode 100644 tests/ui/closures/mut-autoreborrow-closure-cursed-fail.rs create mode 100644 tests/ui/closures/mut-autoreborrow-closure-cursed-fail.stderr create mode 100644 tests/ui/closures/mut-autoreborrow-closure-cursed.rs create mode 100644 tests/ui/closures/mut-autoreborrow-closure-fail.rs create mode 100644 tests/ui/closures/mut-autoreborrow-closure-fail.stderr create mode 100644 tests/ui/closures/mut-autoreborrow-closure-win.rs create mode 100644 tests/ui/reborrow/mut-autoreborrow-fail.rs create mode 100644 tests/ui/reborrow/mut-autoreborrow-fail.stderr diff --git a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs index 09c76d6beb4a1..b36a6ce6952ac 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs @@ -294,7 +294,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // by reference captures use as_operand Some(Category::Place) => { let place = unpack!(block = this.as_place(block, upvar)); - this.consume_by_copy_or_move(place) + this.consume_by_copy_reborrow_or_move(place, block, upvar_expr.span) } _ => { // Turn mutable borrow captures into unique diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index 6ca12032362be..2da77b3079e8a 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -371,14 +371,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) .into_block(); + let arg = this.consume_by_copy_reborrow_or_move( + state_result_place, + block, + scrutinee_span, + ); this.cfg.push_assign( block, source_info, state_place, - Rvalue::Use( - this.consume_by_copy_or_move(state_result_place), - WithRetag::Yes, - ), + Rvalue::Use(arg, WithRetag::Yes), ); block.unit() }, @@ -642,7 +644,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { None => { let place = place_builder.clone_project(PlaceElem::Field(n, *ty)); - this.consume_by_copy_or_move(place.to_place(this)) + this.consume_by_copy_reborrow_or_move( + place.to_place(this), + block, + this.thir.exprs[*base].span, + ) } }) .collect() @@ -839,7 +845,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { debug_assert!(Category::of(&expr.kind) == Some(Category::Place)); let place = unpack!(block = this.as_place(block, expr_id)); - let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place), WithRetag::Yes); + let rvalue = Rvalue::Use( + this.consume_by_copy_reborrow_or_move(place, block, expr.span), + WithRetag::Yes, + ); this.cfg.push_assign(block, source_info, destination, rvalue); block.unit() } @@ -854,7 +863,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } let place = unpack!(block = this.as_place(block, expr_id)); - let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place), WithRetag::Yes); + let rvalue = Rvalue::Use( + this.consume_by_copy_reborrow_or_move(place, block, expr.span), + WithRetag::Yes, + ); this.cfg.push_assign(block, source_info, destination, rvalue); block.unit() } diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 1e65ddf3372a9..97b958b72cccf 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -2723,9 +2723,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.schedule_drop_for_binding(binding.var_id, binding.span, OutsideGuard); } let rvalue = match binding.binding_mode.0 { - ByRef::No => { - Rvalue::Use(self.consume_by_copy_or_move(binding.source), WithRetag::Yes) - } + ByRef::No => Rvalue::Use( + self.consume_by_copy_reborrow_or_move(binding.source, block, binding.span), + WithRetag::Yes, + ), ByRef::Yes(pinnedness, mutbl) => { let rvalue = Rvalue::Ref(re_erased, util::ref_pat_borrow_kind(mutbl), binding.source); diff --git a/compiler/rustc_mir_build/src/builder/misc.rs b/compiler/rustc_mir_build/src/builder/misc.rs index 6e8e74fd4fc8d..5e21a3ce806a4 100644 --- a/compiler/rustc_mir_build/src/builder/misc.rs +++ b/compiler/rustc_mir_build/src/builder/misc.rs @@ -7,7 +7,7 @@ use rustc_span::Span; use rustc_trait_selection::infer::InferCtxtExt; use tracing::debug; -use crate::builder::Builder; +use crate::builder::{Builder, PlaceBuilder}; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Adds a new temporary value of type `ty` storing the result of @@ -58,11 +58,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { temp } - pub(crate) fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> { + pub(crate) fn consume_by_copy_reborrow_or_move( + &mut self, + place: Place<'tcx>, + block: BasicBlock, + span: Span, + ) -> Operand<'tcx> { let tcx = self.tcx; let ty = place.ty(&self.local_decls, tcx).ty; + if self.infcx.type_is_copy_modulo_regions(self.param_env, ty) { Operand::Copy(place) + } else if let ty::Ref(_, _, Mutability::Mut) = ty.kind() { + // Reborrow the mutable reference. + let reborrow = self.temp(ty, span); + let deref = PlaceBuilder::from(place).project(ProjectionElem::Deref).to_place(self); + self.cfg.push_assign( + block, + self.source_info(span), + reborrow, + Rvalue::Ref( + tcx.lifetimes.re_erased, + BorrowKind::Mut { kind: MutBorrowKind::Default }, + deref, + ), + ); + Operand::Move(reborrow) } else { Operand::Move(place) } diff --git a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-unwind.diff index 23943f474661e..9df4ba62b566f 100644 --- a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-unwind.diff @@ -5,8 +5,10 @@ debug x => _1; let mut _0: (); let _2: &mut u8; - let _5: (); - let mut _6: &mut u8; + let mut _5: &mut u8; + let _6: (); + let mut _7: &mut u8; + let mut _8: &mut u8; scope 1 { debug a => _2; let _3: &mut u8; @@ -15,7 +17,7 @@ let _4: &mut u8; scope 3 { - debug c => _4; -+ debug c => _2; ++ debug c => _5; } } } @@ -26,17 +28,20 @@ StorageLive(_3); _3 = &mut (*_2); - StorageLive(_4); -- _4 = move _2; - StorageLive(_5); -- StorageLive(_6); -- _6 = move _4; -- _5 = opaque::<&mut u8>(move _6) -> [return: bb1, unwind continue]; -+ _5 = opaque::<&mut u8>(copy _2) -> [return: bb1, unwind continue]; + _5 = &mut (*_2); +- _4 = move _5; + StorageLive(_6); +- StorageLive(_7); +- _8 = &mut (*_4); +- _7 = move _8; +- _6 = opaque::<&mut u8>(move _7) -> [return: bb1, unwind continue]; ++ _8 = &mut (*_5); ++ _6 = opaque::<&mut u8>(copy _8) -> [return: bb1, unwind continue]; } bb1: { -- StorageDead(_6); - StorageDead(_5); +- StorageDead(_7); + StorageDead(_6); _0 = const (); - StorageDead(_4); StorageDead(_3); diff --git a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-unwind.diff index 8a428ef12cdde..d73c15f8a9fed 100644 --- a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-unwind.diff @@ -5,8 +5,10 @@ debug x => _1; let mut _0: (); let _2: &mut u8; - let _5: (); - let mut _6: &mut u8; + let mut _5: &mut u8; + let _6: (); + let mut _7: &mut u8; + let mut _8: &mut u8; scope 1 { debug a => _2; let _3: *mut u8; @@ -15,7 +17,7 @@ let _4: &mut u8; scope 3 { - debug c => _4; -+ debug c => _2; ++ debug c => _5; } } } @@ -26,17 +28,20 @@ StorageLive(_3); _3 = &raw mut (*_2); - StorageLive(_4); -- _4 = move _2; - StorageLive(_5); -- StorageLive(_6); -- _6 = move _4; -- _5 = opaque::<&mut u8>(move _6) -> [return: bb1, unwind continue]; -+ _5 = opaque::<&mut u8>(copy _2) -> [return: bb1, unwind continue]; + _5 = &mut (*_2); +- _4 = move _5; + StorageLive(_6); +- StorageLive(_7); +- _8 = &mut (*_4); +- _7 = move _8; +- _6 = opaque::<&mut u8>(move _7) -> [return: bb1, unwind continue]; ++ _8 = &mut (*_5); ++ _6 = opaque::<&mut u8>(copy _8) -> [return: bb1, unwind continue]; } bb1: { -- StorageDead(_6); - StorageDead(_5); +- StorageDead(_7); + StorageDead(_6); _0 = const (); - StorageDead(_4); StorageDead(_3); diff --git a/tests/mir-opt/gvn.references.GVN.panic-unwind.diff b/tests/mir-opt/gvn.references.GVN.panic-unwind.diff index c2d67507c39d3..7c458a932b114 100644 --- a/tests/mir-opt/gvn.references.GVN.panic-unwind.diff +++ b/tests/mir-opt/gvn.references.GVN.panic-unwind.diff @@ -23,14 +23,17 @@ let _18: &mut impl Sized; let mut _20: S<&mut impl Sized>; let mut _21: &mut impl Sized; - let _22: (); - let mut _23: &impl Sized; + let mut _22: &mut impl Sized; + let mut _23: &mut impl Sized; let _24: (); - let mut _25: &mut impl Sized; + let mut _25: &impl Sized; let _26: (); - let mut _27: *const impl Sized; + let mut _27: &mut impl Sized; let _28: (); - let mut _29: *mut impl Sized; + let mut _29: *const impl Sized; + let _30: (); + let mut _31: *mut impl Sized; + let mut _32: &mut impl Sized; scope 1 { debug r => _18; let _19: &mut impl Sized; @@ -117,54 +120,59 @@ StorageLive(_19); StorageLive(_20); StorageLive(_21); -- _21 = move _18; + _22 = &mut (*_18); +- _21 = move _22; - _20 = S::<&mut impl Sized>(move _21); -+ _21 = copy _18; -+ _20 = S::<&mut impl Sized>(copy _18); ++ _21 = copy _22; ++ _20 = S::<&mut impl Sized>(copy _22); StorageDead(_21); -- _19 = move (_20.0: &mut impl Sized); -+ _19 = copy _18; +- _32 = no_retag copy (_20.0: &mut impl Sized); +- _23 = &mut (*_32); +- _19 = move _23; ++ _32 = no_retag copy _22; ++ _23 = &mut (*_22); ++ _19 = copy _23; StorageDead(_20); - StorageLive(_22); - StorageLive(_23); -- _23 = &(*_19); -+ _23 = &(*_18); - _22 = opaque::<&impl Sized>(move _23) -> [return: bb9, unwind: bb14]; - } - - bb9: { - StorageDead(_23); - StorageDead(_22); StorageLive(_24); StorageLive(_25); -- _25 = &mut (*_19); -+ _25 = &mut (*_18); - _24 = opaque::<&mut impl Sized>(move _25) -> [return: bb10, unwind: bb14]; +- _25 = &(*_19); ++ _25 = &(*_23); + _24 = opaque::<&impl Sized>(move _25) -> [return: bb9, unwind: bb14]; } - bb10: { + bb9: { StorageDead(_25); StorageDead(_24); StorageLive(_26); StorageLive(_27); -- _27 = &raw const (*_19); -+ _27 = &raw const (*_18); - _26 = opaque::<*const impl Sized>(move _27) -> [return: bb11, unwind: bb14]; +- _27 = &mut (*_19); ++ _27 = &mut (*_23); + _26 = opaque::<&mut impl Sized>(move _27) -> [return: bb10, unwind: bb14]; } - bb11: { + bb10: { StorageDead(_27); StorageDead(_26); StorageLive(_28); StorageLive(_29); -- _29 = &raw mut (*_19); -+ _29 = &raw mut (*_18); - _28 = opaque::<*mut impl Sized>(move _29) -> [return: bb12, unwind: bb14]; +- _29 = &raw const (*_19); ++ _29 = &raw const (*_23); + _28 = opaque::<*const impl Sized>(move _29) -> [return: bb11, unwind: bb14]; } - bb12: { + bb11: { StorageDead(_29); StorageDead(_28); + StorageLive(_30); + StorageLive(_31); +- _31 = &raw mut (*_19); ++ _31 = &raw mut (*_23); + _30 = opaque::<*mut impl Sized>(move _31) -> [return: bb12, unwind: bb14]; + } + + bb12: { + StorageDead(_31); + StorageDead(_30); _0 = const (); StorageDead(_19); StorageDead(_18); diff --git a/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-unwind.diff index d18bdc431683f..787a31367db8d 100644 --- a/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-unwind.diff +++ b/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-unwind.diff @@ -13,13 +13,14 @@ let mut _8: usize; let mut _9: &mut i16; let mut _10: &mut [i16]; - let mut _11: usize; - let mut _12: *const i32; - let mut _13: *const [i32]; - let mut _14: usize; - let mut _15: *mut i64; - let mut _16: *mut [i64]; - let mut _17: usize; + let mut _11: &mut [i16]; + let mut _12: usize; + let mut _13: *const i32; + let mut _14: *const [i32]; + let mut _15: usize; + let mut _16: *mut i64; + let mut _17: *mut [i64]; + let mut _18: usize; bb0: { StorageLive(_6); @@ -37,46 +38,47 @@ StorageDead(_7); StorageLive(_9); StorageLive(_10); - _10 = move _2; - StorageLive(_11); - _11 = copy _5; -- _9 = slice_get_unchecked::<&mut i16, &mut [i16], i16>(move _10, move _11) -> [return: bb2, unwind unreachable]; -+ _9 = &mut (*_10)[_11]; + _11 = &mut (*_2); + _10 = move _11; + StorageLive(_12); + _12 = copy _5; +- _9 = slice_get_unchecked::<&mut i16, &mut [i16], i16>(move _10, move _12) -> [return: bb2, unwind unreachable]; ++ _9 = &mut (*_10)[_12]; + goto -> bb2; } bb2: { - StorageDead(_11); + StorageDead(_12); StorageDead(_10); - StorageLive(_12); StorageLive(_13); - _13 = copy _3; StorageLive(_14); - _14 = copy _5; -- _12 = slice_get_unchecked::<*const i32, *const [i32], i32>(move _13, move _14) -> [return: bb3, unwind unreachable]; -+ _12 = &raw const (*_13)[_14]; + _14 = copy _3; + StorageLive(_15); + _15 = copy _5; +- _13 = slice_get_unchecked::<*const i32, *const [i32], i32>(move _14, move _15) -> [return: bb3, unwind unreachable]; ++ _13 = &raw const (*_14)[_15]; + goto -> bb3; } bb3: { + StorageDead(_15); StorageDead(_14); - StorageDead(_13); - StorageLive(_15); StorageLive(_16); - _16 = copy _4; StorageLive(_17); - _17 = copy _5; -- _15 = slice_get_unchecked::<*mut i64, *mut [i64], i64>(move _16, move _17) -> [return: bb4, unwind unreachable]; -+ _15 = &raw mut (*_16)[_17]; + _17 = copy _4; + StorageLive(_18); + _18 = copy _5; +- _16 = slice_get_unchecked::<*mut i64, *mut [i64], i64>(move _17, move _18) -> [return: bb4, unwind unreachable]; ++ _16 = &raw mut (*_17)[_18]; + goto -> bb4; } bb4: { + StorageDead(_18); StorageDead(_17); + _0 = (move _6, move _9, move _13, move _16); StorageDead(_16); - _0 = (move _6, move _9, move _12, move _15); - StorageDead(_15); - StorageDead(_12); + StorageDead(_13); StorageDead(_9); StorageDead(_6); return; diff --git a/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff index e2fab8a5f2e4d..52e625f141284 100644 --- a/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff +++ b/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff @@ -27,27 +27,31 @@ let mut _33: usize; let _36: (); let mut _37: &mut usize; - let _38: (); - let mut _39: usize; - let _45: (); - let mut _46: &mut usize; - let _47: (); - let _48: &mut T; - let _50: (); - let mut _51: (); - let _52: (); - let _53: &mut T; - let mut _54: &mut T; - let mut _55: &mut T; - let _57: (); - let mut _58: (); - let _59: (); - let mut _60: usize; - let _64: (); - let mut _65: (); - let mut _66: usize; - let _70: (); - let mut _71: (); + let mut _38: &mut usize; + let _39: (); + let mut _40: usize; + let mut _44: &mut usize; + let mut _47: &mut usize; + let _48: (); + let mut _49: &mut usize; + let mut _50: &mut usize; + let _51: (); + let _52: &mut T; + let _54: (); + let mut _55: (); + let _56: (); + let _57: &mut T; + let mut _58: &mut T; + let mut _59: &mut T; + let _61: (); + let mut _62: (); + let _63: (); + let mut _64: usize; + let _68: (); + let mut _69: (); + let mut _70: usize; + let _74: (); + let mut _75: (); scope 1 { debug a => _4; let _5: &mut usize; @@ -116,22 +120,24 @@ } } scope 19 { - debug a => _39; - let _40: &mut usize; + debug a => _40; + let _41: &mut usize; scope 20 { - debug b1 => _40; - let _41: usize; + debug b1 => _41; + let _42: usize; scope 21 { - debug c => _41; - let _42: &mut usize; + debug c => _42; + let _43: &mut usize; scope 22 { - debug b2 => _42; - let _43: usize; +- debug b2 => _43; ++ debug b2 => _41; + let _45: usize; scope 23 { - debug c2 => _43; - let _44: &mut usize; + debug c2 => _45; + let _46: &mut usize; scope 24 { - debug b3 => _44; +- debug b3 => _46; ++ debug b3 => _41; } } } @@ -139,46 +145,46 @@ } } scope 25 { -- debug a => _48; +- debug a => _52; + debug a => _1; - let _49: T; + let _53: T; scope 26 { - debug b => _49; + debug b => _53; } } scope 27 { - debug a => _53; - let _56: T; + debug a => _57; + let _60: T; scope 28 { - debug b => _56; + debug b => _60; } } scope 29 { - debug a => _60; - let _61: &mut usize; + debug a => _64; + let _65: &mut usize; scope 30 { - debug b => _61; - let _62: &&mut usize; + debug b => _65; + let _66: &&mut usize; scope 31 { - debug d => _62; - let _63: usize; + debug d => _66; + let _67: usize; scope 32 { - debug c => _63; + debug c => _67; } } } } scope 33 { - debug a => _66; - let mut _67: &mut usize; + debug a => _70; + let mut _71: &mut usize; scope 34 { - debug b => _67; - let _68: &mut &mut usize; + debug b => _71; + let _72: &mut &mut usize; scope 35 { - debug d => _68; - let _69: usize; + debug d => _72; + let _73: usize; scope 36 { - debug c => _69; + debug c => _73; } } } @@ -296,12 +302,15 @@ StorageLive(_34); _34 = &mut _33; StorageLive(_35); - _35 = copy (*_34); +- _35 = copy (*_34); ++ _35 = copy _33; StorageLive(_36); StorageLive(_37); -- _37 = move _34; +- _38 = &mut (*_34); +- _37 = move _38; - _36 = opaque::<&mut usize>(move _37) -> [return: bb5, unwind continue]; -+ _37 = copy _34; ++ _38 = &mut _33; ++ _37 = copy _38; + _36 = opaque::<&mut usize>(copy _37) -> [return: bb5, unwind continue]; } @@ -313,132 +322,136 @@ StorageDead(_34); StorageDead(_33); - StorageDead(_32); -- StorageLive(_38); - StorageLive(_39); - _39 = const 7_usize; +- StorageLive(_39); StorageLive(_40); - _40 = &mut _39; - StorageLive(_41); - _41 = copy (*_40); + _40 = const 7_usize; +- StorageLive(_41); + _41 = &mut _40; StorageLive(_42); -- _42 = move _40; +- _42 = copy (*_41); +- StorageLive(_43); +- _44 = &mut (*_41); +- _43 = move _44; + _42 = copy _40; - StorageLive(_43); - _43 = copy (*_42); - StorageLive(_44); -- _44 = move _42; -+ _44 = copy _42; StorageLive(_45); - StorageLive(_46); -- _46 = move _44; -- _45 = opaque::<&mut usize>(move _46) -> [return: bb6, unwind continue]; -+ _46 = copy _44; -+ _45 = opaque::<&mut usize>(copy _46) -> [return: bb6, unwind continue]; +- _45 = copy (*_43); +- StorageLive(_46); +- _47 = &mut (*_43); +- _46 = move _47; ++ _45 = copy _40; + StorageLive(_48); + StorageLive(_49); +- _50 = &mut (*_46); +- _49 = move _50; +- _48 = opaque::<&mut usize>(move _49) -> [return: bb6, unwind continue]; ++ _50 = &mut _40; ++ _49 = copy _50; ++ _48 = opaque::<&mut usize>(copy _49) -> [return: bb6, unwind continue]; } bb6: { - StorageDead(_46); + StorageDead(_49); + StorageDead(_48); +- _39 = const (); +- StorageDead(_46); StorageDead(_45); -- _38 = const (); - StorageDead(_44); - StorageDead(_43); +- StorageDead(_43); StorageDead(_42); - StorageDead(_41); +- StorageDead(_41); StorageDead(_40); - StorageDead(_39); -- StorageDead(_38); -- StorageLive(_47); -- StorageLive(_48); -- _48 = &mut (*_1); - StorageLive(_49); -- _49 = copy (*_48); -+ _49 = copy (*_1); - StorageLive(_50); - StorageLive(_51); - _51 = (); - _50 = opaque::<()>(move _51) -> [return: bb7, unwind continue]; - } - - bb7: { - StorageDead(_51); - StorageDead(_50); -- _47 = const (); - StorageDead(_49); -- StorageDead(_48); -- StorageDead(_47); +- StorageDead(_39); +- StorageLive(_51); - StorageLive(_52); +- _52 = &mut (*_1); StorageLive(_53); - _53 = &mut (*_2); +- _53 = copy (*_52); ++ _53 = copy (*_1); StorageLive(_54); -- StorageLive(_55); -- _55 = &mut (*_1); -- _54 = &mut (*_55); -- _2 = move _54; -+ _54 = &mut (*_1); -+ _2 = copy _54; - StorageDead(_54); -- StorageDead(_55); - StorageLive(_56); - _56 = copy (*_53); - StorageLive(_57); - StorageLive(_58); - _58 = (); - _57 = opaque::<()>(move _58) -> [return: bb8, unwind continue]; + StorageLive(_55); + _55 = (); + _54 = opaque::<()>(move _55) -> [return: bb7, unwind continue]; } - bb8: { - StorageDead(_58); - StorageDead(_57); -- _52 = const (); - StorageDead(_56); + bb7: { + StorageDead(_55); + StorageDead(_54); +- _51 = const (); StorageDead(_53); - StorageDead(_52); +- StorageDead(_51); +- StorageLive(_56); + StorageLive(_57); + _57 = &mut (*_2); + StorageLive(_58); - StorageLive(_59); +- _59 = &mut (*_1); +- _58 = &mut (*_59); +- _2 = move _58; ++ _58 = &mut (*_1); ++ _2 = copy _58; + StorageDead(_58); +- StorageDead(_59); StorageLive(_60); - _60 = const 5_usize; + _60 = copy (*_57); StorageLive(_61); - _61 = &mut _60; StorageLive(_62); - _62 = &_61; - StorageLive(_63); - _63 = copy (*_61); - StorageLive(_64); - StorageLive(_65); - _65 = (); - _64 = opaque::<()>(move _65) -> [return: bb9, unwind continue]; + _62 = (); + _61 = opaque::<()>(move _62) -> [return: bb8, unwind continue]; } - bb9: { - StorageDead(_65); - StorageDead(_64); -- _59 = const (); - StorageDead(_63); + bb8: { StorageDead(_62); StorageDead(_61); +- _56 = const (); StorageDead(_60); -- StorageDead(_59); + StorageDead(_57); +- StorageDead(_56); +- StorageLive(_63); + StorageLive(_64); + _64 = const 5_usize; + StorageLive(_65); + _65 = &mut _64; StorageLive(_66); - _66 = const 5_usize; + _66 = &_65; StorageLive(_67); - _67 = &mut _66; + _67 = copy (*_65); StorageLive(_68); - _68 = &mut _67; StorageLive(_69); - _69 = copy (*_67); + _69 = (); + _68 = opaque::<()>(move _69) -> [return: bb9, unwind continue]; + } + + bb9: { + StorageDead(_69); + StorageDead(_68); +- _63 = const (); + StorageDead(_67); + StorageDead(_66); + StorageDead(_65); + StorageDead(_64); +- StorageDead(_63); StorageLive(_70); + _70 = const 5_usize; StorageLive(_71); - _71 = (); - _70 = opaque::<()>(move _71) -> [return: bb10, unwind continue]; + _71 = &mut _70; + StorageLive(_72); + _72 = &mut _71; + StorageLive(_73); + _73 = copy (*_71); + StorageLive(_74); + StorageLive(_75); + _75 = (); + _74 = opaque::<()>(move _75) -> [return: bb10, unwind continue]; } bb10: { + StorageDead(_75); + StorageDead(_74); + _0 = const (); + StorageDead(_73); + StorageDead(_72); StorageDead(_71); StorageDead(_70); - _0 = const (); - StorageDead(_69); - StorageDead(_68); - StorageDead(_67); - StorageDead(_66); return; } } diff --git a/tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs b/tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs index 389b8a43c0551..2ce1fc83a0a91 100644 --- a/tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs +++ b/tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs @@ -9,7 +9,7 @@ struct Foo { fn main() { let mut y = 1; let x = Some(&mut y); - for &a in x.iter() { //~ ERROR cannot move out + for &a in x.iter() { //~ ERROR cannot borrow data in a `&` reference as mutable } let f = Foo { diff --git a/tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr b/tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr index 1ff5c78df7808..734c761341783 100644 --- a/tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr +++ b/tests/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.stderr @@ -1,16 +1,10 @@ -error[E0507]: cannot move out of a shared reference - --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:12:15 +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:12:10 | LL | for &a in x.iter() { - | - ^^^^^^^^ + | ^ -------- this cannot be borrowed as mutable | | - | data moved here because `a` has type `&mut i32`, which does not implement the `Copy` trait - | -help: consider removing the borrow - | -LL - for &a in x.iter() { -LL + for a in x.iter() { - | + | cannot borrow as mutable error[E0507]: cannot move out of a shared reference --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:18:15 @@ -42,4 +36,5 @@ LL + for a in x.iter() { error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0507`. +Some errors have detailed explanations: E0507, E0596. +For more information about an error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/borrowck-issue-48962.rs b/tests/ui/borrowck/borrowck-issue-48962.rs index 86061c8cd6e87..c6252c108a9ca 100644 --- a/tests/ui/borrowck/borrowck-issue-48962.rs +++ b/tests/ui/borrowck/borrowck-issue-48962.rs @@ -1,23 +1,25 @@ +//@ run-pass + struct Node { - elem: i32, next: Option>, } fn a() { - let mut node = Node { - elem: 5, - next: None, - }; + let mut node = Node { next: None }; - let mut src = &mut node; - {src}; - src.next = None; //~ ERROR use of moved value: `src` [E0382] + let src = &mut node; + { + src + }; + src.next = None; } fn b() { - let mut src = &mut (22, 44); - {src}; - src.0 = 66; //~ ERROR use of moved value: `src` [E0382] + let src = &mut (22, 44); + { + src + }; + src.0 = 66; } fn main() { diff --git a/tests/ui/borrowck/borrowck-issue-48962.stderr b/tests/ui/borrowck/borrowck-issue-48962.stderr deleted file mode 100644 index ee174f6736e1e..0000000000000 --- a/tests/ui/borrowck/borrowck-issue-48962.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0382]: use of moved value: `src` - --> $DIR/borrowck-issue-48962.rs:14:5 - | -LL | let mut src = &mut node; - | ------- move occurs because `src` has type `&mut Node`, which does not implement the `Copy` trait -LL | {src}; - | --- value moved here -LL | src.next = None; - | ^^^^^^^^ value used here after move - -error[E0382]: use of moved value: `src` - --> $DIR/borrowck-issue-48962.rs:20:5 - | -LL | let mut src = &mut (22, 44); - | ------- move occurs because `src` has type `&mut (i32, i32)`, which does not implement the `Copy` trait -LL | {src}; - | --- value moved here -LL | src.0 = 66; - | ^^^^^^^^^^ value used here after move - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/borrowck-move-mut-base-ptr.rs b/tests/ui/borrowck/borrowck-move-mut-base-ptr.rs index fa2d5531b1393..e4c63e7ba06cb 100644 --- a/tests/ui/borrowck/borrowck-move-mut-base-ptr.rs +++ b/tests/ui/borrowck/borrowck-move-mut-base-ptr.rs @@ -7,7 +7,7 @@ fn foo(t0: &mut isize) { let p: &isize = &*t0; // Freezes `*t0` - let t1 = t0; //~ ERROR cannot move out of `t0` + let t1 = t0; //~ ERROR cannot borrow `*t0` as mutable because it is also borrowed as immutable *t1 = 22; p.use_ref(); } diff --git a/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr b/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr index 4b9351b64a038..0e42dfc520ce0 100644 --- a/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr +++ b/tests/ui/borrowck/borrowck-move-mut-base-ptr.stderr @@ -1,22 +1,14 @@ -error[E0505]: cannot move out of `t0` because it is borrowed +error[E0502]: cannot borrow `*t0` as mutable because it is also borrowed as immutable --> $DIR/borrowck-move-mut-base-ptr.rs:10:14 | -LL | fn foo(t0: &mut isize) { - | -- binding `t0` declared here LL | let p: &isize = &*t0; // Freezes `*t0` - | ---- borrow of `*t0` occurs here + | ---- immutable borrow occurs here LL | let t1 = t0; - | ^^ move out of `t0` occurs here + | ^^ mutable borrow occurs here LL | *t1 = 22; LL | p.use_ref(); - | - borrow later used here - | -help: consider cloning the value if the performance cost is acceptable - | -LL - let p: &isize = &*t0; // Freezes `*t0` -LL + let p: &isize = &t0.clone(); // Freezes `*t0` - | + | - immutable borrow later used here error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0505`. +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/borrowck/fn-closure-move-capture-no-reborrow-sugg.rs b/tests/ui/borrowck/fn-closure-move-capture-no-reborrow-sugg.rs index 4f0c65dd5bd2a..cb42d2657a671 100644 --- a/tests/ui/borrowck/fn-closure-move-capture-no-reborrow-sugg.rs +++ b/tests/ui/borrowck/fn-closure-move-capture-no-reborrow-sugg.rs @@ -29,7 +29,7 @@ pub fn in_fn_mut Result<(), ()>>(mut f: F) -> Result<(), ()> { pub fn fn_closure(foos: &mut [&mut Foo]) -> Result<(), ()> { in_fn(|| { for _ in foos { - //~^ ERROR cannot move out of `foos`, a captured variable in an `Fn` closure + //~^ ERROR cannot borrow `*foos` as mutable, as `Fn` closures cannot mutate their captured variables } Ok(()) }) @@ -38,9 +38,7 @@ pub fn fn_closure(foos: &mut [&mut Foo]) -> Result<(), ()> { // `FnMut` closure: a mutable reborrow is valid, so the suggestion is offered. pub fn fn_mut_closure(foos: &mut [&mut Foo]) -> Result<(), ()> { in_fn_mut(|| { - for _ in foos { - //~^ ERROR cannot move out of `foos`, a captured variable in an `FnMut` closure - } + for _ in foos {} Ok(()) }) } diff --git a/tests/ui/borrowck/fn-closure-move-capture-no-reborrow-sugg.stderr b/tests/ui/borrowck/fn-closure-move-capture-no-reborrow-sugg.stderr index f92951313f2a4..15fd0e429c9e7 100644 --- a/tests/ui/borrowck/fn-closure-move-capture-no-reborrow-sugg.stderr +++ b/tests/ui/borrowck/fn-closure-move-capture-no-reborrow-sugg.stderr @@ -1,53 +1,16 @@ -error[E0507]: cannot move out of `foos`, a captured variable in an `Fn` closure +error[E0596]: cannot borrow `*foos` as mutable, as `Fn` closures cannot mutate their captured variables --> $DIR/fn-closure-move-capture-no-reborrow-sugg.rs:31:18 | -LL | pub fn fn_closure(foos: &mut [&mut Foo]) -> Result<(), ()> { - | ---- --------------- move occurs because `foos` has type `&mut [&mut Foo]`, which does not implement the `Copy` trait - | | - | captured outer variable -LL | in_fn(|| { - | -- captured by this `Fn` closure -LL | for _ in foos { - | ^^^^ - | | - | `foos` moved due to this implicit call to `.into_iter()` - | `foos` is moved here - | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once - --> $DIR/fn-closure-move-capture-no-reborrow-sugg.rs:20:17 - | LL | pub fn in_fn Result<(), ()>>(f: F) -> Result<(), ()> { - | ^^^^^^^^^^^^^^^^^^^^^^ -note: the `for` loop is desugared into a call to `std::iter::IntoIterator::into_iter`, which takes ownership of the receiver `self`, which moves `foos` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL - -error[E0507]: cannot move out of `foos`, a captured variable in an `FnMut` closure - --> $DIR/fn-closure-move-capture-no-reborrow-sugg.rs:41:18 - | -LL | pub fn fn_mut_closure(foos: &mut [&mut Foo]) -> Result<(), ()> { - | ---- --------------- move occurs because `foos` has type `&mut [&mut Foo]`, which does not implement the `Copy` trait - | | - | captured outer variable -LL | in_fn_mut(|| { - | -- captured by this `FnMut` closure + | - change this to accept `FnMut` instead of `Fn` +... +LL | in_fn(|| { + | ----- -- in this closure + | | + | expects `Fn` instead of `FnMut` LL | for _ in foos { - | ^^^^ - | | - | `foos` moved due to this implicit call to `.into_iter()` - | `foos` is moved here - | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once - --> $DIR/fn-closure-move-capture-no-reborrow-sugg.rs:24:21 - | -LL | pub fn in_fn_mut Result<(), ()>>(mut f: F) -> Result<(), ()> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -note: the `for` loop is desugared into a call to `std::iter::IntoIterator::into_iter`, which takes ownership of the receiver `self`, which moves `foos` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL -help: consider creating a fresh reborrow of `foos` here - | -LL | for _ in &mut *foos { - | ++++++ + | ^^^^ cannot borrow as mutable -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0507`. +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/borrowck/issue-101119.rs b/tests/ui/borrowck/issue-101119.rs index 64e52eaac06e5..ddefbdd22bbee 100644 --- a/tests/ui/borrowck/issue-101119.rs +++ b/tests/ui/borrowck/issue-101119.rs @@ -1,11 +1,12 @@ +//@ run-pass + struct State; fn once(_: impl FnOnce()) {} fn fill_memory_blocks_mt(state: &mut State) { - loop { + for _ in 0..100 { once(move || { - //~^ ERROR use of moved value: `state` fill_segment(state); }); } @@ -13,4 +14,6 @@ fn fill_memory_blocks_mt(state: &mut State) { fn fill_segment(_: &mut State) {} -fn main() {} +fn main() { + fill_memory_blocks_mt(&mut State); +} diff --git a/tests/ui/borrowck/issue-101119.stderr b/tests/ui/borrowck/issue-101119.stderr deleted file mode 100644 index 7fec81b59b3a8..0000000000000 --- a/tests/ui/borrowck/issue-101119.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error[E0382]: use of moved value: `state` - --> $DIR/issue-101119.rs:7:14 - | -LL | fn fill_memory_blocks_mt(state: &mut State) { - | ----- move occurs because `state` has type `&mut State`, which does not implement the `Copy` trait -LL | loop { - | ---- inside of this loop -LL | once(move || { - | ^^^^^^^ value moved into closure here, in previous iteration of loop -LL | -LL | fill_segment(state); - | ----- use occurs due to use in closure - | -note: consider changing this parameter type in function `fill_segment` to borrow instead if owning the value isn't necessary - --> $DIR/issue-101119.rs:14:20 - | -LL | fn fill_segment(_: &mut State) {} - | ------------ ^^^^^^^^^^ this parameter takes ownership of the value - | | - | in this function - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/issue-83924.fixed b/tests/ui/borrowck/issue-83924.fixed deleted file mode 100644 index 891b0bf06509a..0000000000000 --- a/tests/ui/borrowck/issue-83924.fixed +++ /dev/null @@ -1,20 +0,0 @@ -//@ run-rustfix - -fn main() { - let mut values = vec![10, 11, 12]; - let v = &mut values; - - let mut max = 0; - - for n in &mut *v { - max = std::cmp::max(max, *n); - } - - println!("max is {}", max); - println!("Converting to percentages of maximum value..."); - for n in v { - //~^ ERROR: use of moved value: `v` [E0382] - *n = 100 * (*n) / max; - } - println!("values: {:#?}", values); -} diff --git a/tests/ui/borrowck/issue-83924.rs b/tests/ui/borrowck/issue-83924.rs index 9781f6e527b3d..ae7e07df82dd6 100644 --- a/tests/ui/borrowck/issue-83924.rs +++ b/tests/ui/borrowck/issue-83924.rs @@ -1,4 +1,4 @@ -//@ run-rustfix +//@ run-pass fn main() { let mut values = vec![10, 11, 12]; @@ -13,7 +13,6 @@ fn main() { println!("max is {}", max); println!("Converting to percentages of maximum value..."); for n in v { - //~^ ERROR: use of moved value: `v` [E0382] *n = 100 * (*n) / max; } println!("values: {:#?}", values); diff --git a/tests/ui/borrowck/issue-83924.stderr b/tests/ui/borrowck/issue-83924.stderr deleted file mode 100644 index 8844766397ef7..0000000000000 --- a/tests/ui/borrowck/issue-83924.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error[E0382]: use of moved value: `v` - --> $DIR/issue-83924.rs:15:14 - | -LL | let v = &mut values; - | - move occurs because `v` has type `&mut Vec`, which does not implement the `Copy` trait -... -LL | for n in v { - | - `v` moved due to this implicit call to `.into_iter()` -... -LL | for n in v { - | ^ value used here after move - | -note: the `for` loop is desugared into a call to `std::iter::IntoIterator::into_iter`, which takes ownership of the receiver `self`, which moves `v` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL -help: consider creating a fresh reborrow of `v` here - | -LL | for n in &mut *v { - | ++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/move-in-pattern-mut-in-loop.rs b/tests/ui/borrowck/move-in-pattern-mut-in-loop.rs index 4b42f9d4cd580..bb45ea086ac1b 100644 --- a/tests/ui/borrowck/move-in-pattern-mut-in-loop.rs +++ b/tests/ui/borrowck/move-in-pattern-mut-in-loop.rs @@ -1,10 +1,9 @@ -// Regression test for #80913. +//@ run-pass fn main() { let mut x = 42_i32; - let mut opt = Some(&mut x); + let opt = Some(&mut x); for _ in 0..5 { - if let Some(mut _x) = opt {} - //~^ ERROR: use of moved value + if let Some(_x) = opt {} } } diff --git a/tests/ui/borrowck/move-in-pattern-mut-in-loop.stderr b/tests/ui/borrowck/move-in-pattern-mut-in-loop.stderr deleted file mode 100644 index bfbae5be050a8..0000000000000 --- a/tests/ui/borrowck/move-in-pattern-mut-in-loop.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0382]: use of moved value - --> $DIR/move-in-pattern-mut-in-loop.rs:7:21 - | -LL | if let Some(mut _x) = opt {} - | ^^^^^^ value moved here, in previous iteration of loop - | - = note: move occurs because value has type `&mut i32`, which does not implement the `Copy` trait -help: borrow this binding in the pattern to avoid moving the value - | -LL | if let Some(ref mut _x) = opt {} - | +++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.fixed b/tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.fixed deleted file mode 100644 index cec52272feeb9..0000000000000 --- a/tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.fixed +++ /dev/null @@ -1,17 +0,0 @@ -//@ run-rustfix - -#![allow(dead_code)] - -struct X(u32); - -impl X { - fn f(&mut self) { - generic(&mut *self); - self.0 += 1; - //~^ ERROR: use of moved value: `self` [E0382] - } -} - -fn generic(_x: T) {} - -fn main() {} diff --git a/tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.rs b/tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.rs index dd015697fdcdb..d52b8faeb0a58 100644 --- a/tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.rs +++ b/tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.rs @@ -1,4 +1,4 @@ -//@ run-rustfix +//@ run-pass #![allow(dead_code)] @@ -8,7 +8,6 @@ impl X { fn f(&mut self) { generic(self); self.0 += 1; - //~^ ERROR: use of moved value: `self` [E0382] } } diff --git a/tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.stderr b/tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.stderr deleted file mode 100644 index 3da8b6e9dff7f..0000000000000 --- a/tests/ui/borrowck/moved-value-suggest-reborrow-issue-127285.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0382]: use of moved value: `self` - --> $DIR/moved-value-suggest-reborrow-issue-127285.rs:10:9 - | -LL | fn f(&mut self) { - | --------- move occurs because `self` has type `&mut X`, which does not implement the `Copy` trait -LL | generic(self); - | ---- value moved here -LL | self.0 += 1; - | ^^^^^^^^^^^ value used here after move - | -help: consider creating a fresh reborrow of `self` here - | -LL | generic(&mut *self); - | ++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/mut-autoreborrow.rs b/tests/ui/borrowck/mut-autoreborrow.rs new file mode 100644 index 0000000000000..701b0d21bf4da --- /dev/null +++ b/tests/ui/borrowck/mut-autoreborrow.rs @@ -0,0 +1,44 @@ +// Test that `&mut` gets autoreborrowed on every move as expected. +//@ run-pass + +fn generic(_: impl Sized) {} +fn assert_fnmut(_: &mut impl FnMut()) {} + +struct Foo(T); + +fn main() { + let mut_ref = &mut (); + generic(mut_ref); + { + mut_ref + }; + let _local = mut_ref; + let _ = || mut_ref; + let mut _tup: (&mut (),) = (&mut (),); + _tup.0 = mut_ref; + Foo(mut_ref); + Foo { 0: mut_ref }; + let mut f = || { + let _y: &mut _ = mut_ref; + }; + f(); + f(); + assert_fnmut(&mut f); + generic(mut_ref); + + let mut_ref_ref = &mut &mut (); + generic(*mut_ref_ref); + let _local = *mut_ref_ref; + let _ = || *mut_ref_ref; + let mut _tup: (&mut (),) = (&mut (),); + _tup.0 = *mut_ref_ref; + Foo(*mut_ref_ref); + Foo { 0: *mut_ref_ref }; + let mut f = || { + let _y: &mut _ = *mut_ref_ref; + }; + f(); + f(); + assert_fnmut(&mut f); + generic(*mut_ref_ref); +} diff --git a/tests/ui/borrowck/mut-borrow-in-loop-2.rs b/tests/ui/borrowck/mut-borrow-in-loop-2.rs index f530dfca1a3ff..2d19648c7727b 100644 --- a/tests/ui/borrowck/mut-borrow-in-loop-2.rs +++ b/tests/ui/borrowck/mut-borrow-in-loop-2.rs @@ -1,3 +1,5 @@ +//@ run-pass + #![allow(dead_code)] struct Events(R); @@ -27,7 +29,7 @@ fn this_compiles<'a, R>(value: &'a mut Events) { fn this_does_not<'a, R>(value: &'a mut Events) { for _ in 0..3 { - Other::handle(value); //~ ERROR use of moved value: `value` + Other::handle(value); } } diff --git a/tests/ui/borrowck/mut-borrow-in-loop-2.stderr b/tests/ui/borrowck/mut-borrow-in-loop-2.stderr deleted file mode 100644 index 46e06bc91b91c..0000000000000 --- a/tests/ui/borrowck/mut-borrow-in-loop-2.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0382]: use of moved value: `value` - --> $DIR/mut-borrow-in-loop-2.rs:30:23 - | -LL | fn this_does_not<'a, R>(value: &'a mut Events) { - | ----- move occurs because `value` has type `&mut Events`, which does not implement the `Copy` trait -LL | for _ in 0..3 { - | ------------- inside of this loop -LL | Other::handle(value); - | ^^^^^ value moved here, in previous iteration of loop - | -help: consider creating a fresh reborrow of `value` here - | -LL | Other::handle(&mut *value); - | ++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/borrowck/reborrow-sugg-move-then-borrow.rs b/tests/ui/borrowck/reborrow-sugg-move-then-borrow.rs index 31eba07400846..205e4532e3c32 100644 --- a/tests/ui/borrowck/reborrow-sugg-move-then-borrow.rs +++ b/tests/ui/borrowck/reborrow-sugg-move-then-borrow.rs @@ -1,5 +1,4 @@ -// Tests the suggestion to reborrow the first move site -// when we move then borrow a `&mut` ref. +//@ run-pass struct State; @@ -12,15 +11,13 @@ impl IntoIterator for &mut State { } } -fn once(f: impl FnOnce()) {} - fn fill_memory_blocks_mt(state: &mut State) { for _ in state {} - //~^ HELP consider creating a fresh reborrow of `state` here fill_segment(state); - //~^ ERROR borrow of moved value: `state` } -fn fill_segment(state: &mut State) {} +fn fill_segment(_state: &mut State) {} -fn main() {} +fn main() { + fill_memory_blocks_mt(&mut State); +} diff --git a/tests/ui/borrowck/reborrow-sugg-move-then-borrow.stderr b/tests/ui/borrowck/reborrow-sugg-move-then-borrow.stderr deleted file mode 100644 index 4cbf323a14662..0000000000000 --- a/tests/ui/borrowck/reborrow-sugg-move-then-borrow.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0382]: borrow of moved value: `state` - --> $DIR/reborrow-sugg-move-then-borrow.rs:20:18 - | -LL | fn fill_memory_blocks_mt(state: &mut State) { - | ----- move occurs because `state` has type `&mut State`, which does not implement the `Copy` trait -LL | for _ in state {} - | ----- `state` moved due to this implicit call to `.into_iter()` -LL | -LL | fill_segment(state); - | ^^^^^ value borrowed here after move - | -note: the `for` loop is desugared into a call to `std::iter::IntoIterator::into_iter`, which takes ownership of the receiver `self`, which moves `state` - --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL -help: consider creating a fresh reborrow of `state` here - | -LL | for _ in &mut *state {} - | ++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/mut-autoreborrow-closure-2024.rs b/tests/ui/closures/mut-autoreborrow-closure-2024.rs new file mode 100644 index 0000000000000..0d8eaf8cf8957 --- /dev/null +++ b/tests/ui/closures/mut-autoreborrow-closure-2024.rs @@ -0,0 +1,9 @@ +//@ edition: 2024.. +//@ run-pass +fn test(x: &mut u8) -> impl FnMut() { + || { let y: &mut u8 = x; *y += 1; } +} + +fn main() { + test(&mut 42)(); +} diff --git a/tests/ui/closures/mut-autoreborrow-closure-cursed-fail.rs b/tests/ui/closures/mut-autoreborrow-closure-cursed-fail.rs new file mode 100644 index 0000000000000..45e1594cc133a --- /dev/null +++ b/tests/ui/closures/mut-autoreborrow-closure-cursed-fail.rs @@ -0,0 +1,19 @@ +//! This cursed example should compile, +//! but doesn't because we have to support `mut-autoreborrow-closure-cursed`. +//! Once we can get closures to implement `Reborrow` +//! and `FnMut` to be implemented for `Reborrow` closures, +//! we will be able to fix this. +//! See https://github.com/rust-lang/rust/issues/47478 + +fn assert_fnmut(_: &mut impl FnMut()) {} + +fn main() { + let x = &mut Box::new(0); + let mut f = || { + // Cursed HIR-inserted reborrow attempts to make this closure `FnMut`, + // but at the cost of never letting us return `y`. + let y: &mut _ = x; + y //~ ERROR captured variable cannot escape `FnMut` closure body + }; + f(); +} diff --git a/tests/ui/closures/mut-autoreborrow-closure-cursed-fail.stderr b/tests/ui/closures/mut-autoreborrow-closure-cursed-fail.stderr new file mode 100644 index 0000000000000..6100ac8e8dd91 --- /dev/null +++ b/tests/ui/closures/mut-autoreborrow-closure-cursed-fail.stderr @@ -0,0 +1,14 @@ +error: captured variable cannot escape `FnMut` closure body + --> $DIR/mut-autoreborrow-closure-cursed-fail.rs:16:9 + | +LL | let mut f = || { + | - inferred to be a `FnMut` closure +... +LL | y + | ^ returns a reference to a captured variable which escapes the closure body + | + = note: `FnMut` closures only have access to their captured variables while they are executing... + = note: ...therefore, they cannot allow references to captured variables to escape + +error: aborting due to 1 previous error + diff --git a/tests/ui/closures/mut-autoreborrow-closure-cursed.rs b/tests/ui/closures/mut-autoreborrow-closure-cursed.rs new file mode 100644 index 0000000000000..0eeeca6f1a015 --- /dev/null +++ b/tests/ui/closures/mut-autoreborrow-closure-cursed.rs @@ -0,0 +1,19 @@ +//! This cursed example should never have compiled +//! (well, not without `Reborrow`), +//! but it does, so we are stuck supporting it forever. +//! See https://github.com/rust-lang/rust/issues/47478 +//@ run-pass + +fn assert_fnmut(_: &mut impl FnMut()) {} + +fn main() { + let x = &mut Box::new(0); + let mut f = || { + // Cursed HIR-inserted reborrow makes this closure `FnMut`, + // but at the cost of never letting us return `_y`. + let _y: &mut _ = x; + }; + f(); + f(); + assert_fnmut(&mut f); +} diff --git a/tests/ui/closures/mut-autoreborrow-closure-fail.rs b/tests/ui/closures/mut-autoreborrow-closure-fail.rs new file mode 100644 index 0000000000000..573af1c89639c --- /dev/null +++ b/tests/ui/closures/mut-autoreborrow-closure-fail.rs @@ -0,0 +1,15 @@ +//! Unlike its evil cousin `mut-autoreborrow-closure-cursed`, +//! this correctly fails to compile. + +fn assert_fnmut(_: &mut impl FnMut()) {} + +fn main() { + let x = &mut Box::new(0); + let mut f = || { + //~^ ERROR expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce` [E0525] + let _y = x; + }; + f(); + f(); + assert_fnmut(&mut f); +} diff --git a/tests/ui/closures/mut-autoreborrow-closure-fail.stderr b/tests/ui/closures/mut-autoreborrow-closure-fail.stderr new file mode 100644 index 0000000000000..ad30043ddd216 --- /dev/null +++ b/tests/ui/closures/mut-autoreborrow-closure-fail.stderr @@ -0,0 +1,23 @@ +error[E0525]: expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce` + --> $DIR/mut-autoreborrow-closure-fail.rs:8:17 + | +LL | let mut f = || { + | ^^ this closure implements `FnOnce`, not `FnMut` +LL | +LL | let _y = x; + | - closure is `FnOnce` because it moves the variable `x` out of its environment +... +LL | assert_fnmut(&mut f); + | ------------ ------ the requirement to implement `FnMut` derives from here + | | + | required by a bound introduced by this call + | +note: required by a bound in `assert_fnmut` + --> $DIR/mut-autoreborrow-closure-fail.rs:4:30 + | +LL | fn assert_fnmut(_: &mut impl FnMut()) {} + | ^^^^^^^ required by this bound in `assert_fnmut` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/closures/mut-autoreborrow-closure-win.rs b/tests/ui/closures/mut-autoreborrow-closure-win.rs new file mode 100644 index 0000000000000..9c8e5fb663586 --- /dev/null +++ b/tests/ui/closures/mut-autoreborrow-closure-win.rs @@ -0,0 +1,12 @@ +//! Test that we can return a captured `&mut` from a closure +//! (because we aren't evil, unlike `mut-autoreborrow-closure-cursed-fail`). +//@ run-pass + +fn main() { + let x = &mut Box::new(0); + let f = || { + let y = x; + y + }; + f(); +} diff --git a/tests/ui/mir-dataflow/inits-1.rs b/tests/ui/mir-dataflow/inits-1.rs index 3331809f3594a..a45e42924877b 100644 --- a/tests/ui/mir-dataflow/inits-1.rs +++ b/tests/ui/mir-dataflow/inits-1.rs @@ -38,8 +38,8 @@ fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { ::std::mem::drop(x); - // `x` is *definitely* uninitialized here - rustc_peek(&x); //~ ERROR rustc_peek: bit not set + // `x` is still initialized here! + rustc_peek(&x); // `ret` is now definitely initialized (via `if` above). rustc_peek(&ret); diff --git a/tests/ui/mir-dataflow/inits-1.stderr b/tests/ui/mir-dataflow/inits-1.stderr index 7a00a70af6f84..2449e257bc029 100644 --- a/tests/ui/mir-dataflow/inits-1.stderr +++ b/tests/ui/mir-dataflow/inits-1.stderr @@ -10,13 +10,7 @@ error: rustc_peek: bit not set LL | rustc_peek(&y); | ^^^^^^^^^^^^^^ -error: rustc_peek: bit not set - --> $DIR/inits-1.rs:42:5 - | -LL | rustc_peek(&x); - | ^^^^^^^^^^^^^^ - error: stop_after_dataflow ended compilation -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/mir-dataflow/uninits-1.rs b/tests/ui/mir-dataflow/uninits-1.rs index c689512833d80..85d3409a0cb73 100644 --- a/tests/ui/mir-dataflow/uninits-1.rs +++ b/tests/ui/mir-dataflow/uninits-1.rs @@ -7,7 +7,7 @@ use std::mem::{drop, replace}; struct S(i32); -#[rustc_mir(rustc_peek_maybe_uninit,stop_after_dataflow)] +#[rustc_mir(rustc_peek_maybe_uninit, stop_after_dataflow)] fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { let ret; // `ret` starts off uninitialized @@ -37,8 +37,8 @@ fn foo(test: bool, x: &mut S, y: S, mut z: S) -> S { ::std::mem::drop(x); - // `x` is *definitely* uninitialized here - rustc_peek(&x); + // `x` is still initialized here! + rustc_peek(&x); //~ ERROR rustc_peek: bit not set // `ret` is now definitely initialized (via `if` above). rustc_peek(&ret); //~ ERROR rustc_peek: bit not set diff --git a/tests/ui/mir-dataflow/uninits-1.stderr b/tests/ui/mir-dataflow/uninits-1.stderr index c52f5ac7bd9b6..825b49f64e222 100644 --- a/tests/ui/mir-dataflow/uninits-1.stderr +++ b/tests/ui/mir-dataflow/uninits-1.stderr @@ -22,6 +22,12 @@ error: rustc_peek: bit not set LL | rustc_peek(&x); | ^^^^^^^^^^^^^^ +error: rustc_peek: bit not set + --> $DIR/uninits-1.rs:41:5 + | +LL | rustc_peek(&x); + | ^^^^^^^^^^^^^^ + error: rustc_peek: bit not set --> $DIR/uninits-1.rs:44:5 | @@ -30,5 +36,5 @@ LL | rustc_peek(&ret); error: stop_after_dataflow ended compilation -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/mir-dataflow/uninits-2.rs b/tests/ui/mir-dataflow/uninits-2.rs index 04daf78e56f71..c047f51bf8351 100644 --- a/tests/ui/mir-dataflow/uninits-2.rs +++ b/tests/ui/mir-dataflow/uninits-2.rs @@ -15,8 +15,8 @@ fn foo(x: &mut S) { ::std::mem::drop(x); - // `x` definitely uninitialized here, so maybe-uninit bit is 1. - rustc_peek(&x); + // `x` is still initialized here, so maybe-uninit bit is 0. + rustc_peek(&x); //~ ERROR rustc_peek: bit not set } fn main() { foo(&mut S(13)); diff --git a/tests/ui/mir-dataflow/uninits-2.stderr b/tests/ui/mir-dataflow/uninits-2.stderr index 0ef954e35a4d8..dc7a6cb21a99b 100644 --- a/tests/ui/mir-dataflow/uninits-2.stderr +++ b/tests/ui/mir-dataflow/uninits-2.stderr @@ -4,7 +4,13 @@ error: rustc_peek: bit not set LL | rustc_peek(&x); | ^^^^^^^^^^^^^^ +error: rustc_peek: bit not set + --> $DIR/uninits-2.rs:19:5 + | +LL | rustc_peek(&x); + | ^^^^^^^^^^^^^^ + error: stop_after_dataflow ended compilation -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/nll/closure-access-spans.rs b/tests/ui/nll/closure-access-spans.rs index 68d1232abb72c..ed5d2c93447b6 100644 --- a/tests/ui/nll/closure-access-spans.rs +++ b/tests/ui/nll/closure-access-spans.rs @@ -43,12 +43,12 @@ fn closure_mut_capture_moved(mut x: String) { fn closure_unique_capture_moved(x: &mut String) { let r = x; - || *x = String::new(); //~ ERROR + || *x = String::new(); } fn closure_move_capture_moved(x: &mut String) { let r = x; - || x; //~ ERROR + || x; } fn main() {} diff --git a/tests/ui/nll/closure-access-spans.stderr b/tests/ui/nll/closure-access-spans.stderr index dc26ebbcfb190..2707fabd96899 100644 --- a/tests/ui/nll/closure-access-spans.stderr +++ b/tests/ui/nll/closure-access-spans.stderr @@ -97,31 +97,7 @@ help: consider cloning the value if the performance cost is acceptable LL | let r = x.clone(); | ++++++++ -error[E0382]: borrow of moved value: `x` - --> $DIR/closure-access-spans.rs:46:5 - | -LL | fn closure_unique_capture_moved(x: &mut String) { - | - move occurs because `x` has type `&mut String`, which does not implement the `Copy` trait -LL | let r = x; - | - value moved here -LL | || *x = String::new(); - | ^^ -- borrow occurs due to use in closure - | | - | value borrowed here after move - -error[E0382]: use of moved value: `x` - --> $DIR/closure-access-spans.rs:51:5 - | -LL | fn closure_move_capture_moved(x: &mut String) { - | - move occurs because `x` has type `&mut String`, which does not implement the `Copy` trait -LL | let r = x; - | - value moved here -LL | || x; - | ^^ - use occurs due to use in closure - | | - | value used here after move - -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0382, E0499, E0500, E0502, E0503, E0505. For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/nll/closure-borrow-spans.stderr b/tests/ui/nll/closure-borrow-spans.stderr index 8ae792f7030cd..49ce23e6170e4 100644 --- a/tests/ui/nll/closure-borrow-spans.stderr +++ b/tests/ui/nll/closure-borrow-spans.stderr @@ -110,17 +110,17 @@ LL | x = 1; LL | f.use_ref(); | - borrow later used here -error[E0505]: cannot move out of `x` because it is borrowed +error[E0501]: cannot borrow `*x` as mutable because previous closure requires unique access --> $DIR/closure-borrow-spans.rs:66:13 | LL | let f = || *x = 0; - | -- -- borrow occurs due to use in closure + | -- -- first borrow occurs due to use of `x` in closure | | - | borrow of `x` occurs here + | closure construction occurs here LL | let y = x; - | ^ move out of `x` occurs here + | ^ second borrow occurs here LL | f.use_ref(); - | - borrow later used here + | - first borrow later used here error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access --> $DIR/closure-borrow-spans.rs:72:13 diff --git a/tests/ui/nll/issue-27282-move-match-input-into-guard.rs b/tests/ui/nll/issue-27282-move-match-input-into-guard.rs index 2650fd560a652..394f2826879a7 100644 --- a/tests/ui/nll/issue-27282-move-match-input-into-guard.rs +++ b/tests/ui/nll/issue-27282-move-match-input-into-guard.rs @@ -10,20 +10,30 @@ fn main() { let b = &mut true; match b { - //~^ ERROR use of moved value: `b` [E0382] - &mut false => {}, - _ if { (|| { let bar = b; *bar = false; })(); - false } => { }, - &mut true => { println!("You might think we should get here"); }, + &mut false => {} + _ if { + (|| { + //~^ ERROR cannot mutably borrow `*b` in match guard + let bar = b; + *bar = false; + })(); + false + } => {} + &mut true => { + println!("You might think we should get here"); + } _ => panic!("surely we could never get here, since rustc warns it is unreachable."), } let b = &mut true; match b { - //~^ ERROR use of moved value: `b` [E0382] &mut false => {} _ if let Some(()) = { - (|| { let bar = b; *bar = false; })(); + (|| { + //~^ ERROR cannot mutably borrow `*b` in match guard + let bar = b; + *bar = false; + })(); None } => {} &mut true => {} diff --git a/tests/ui/nll/issue-27282-move-match-input-into-guard.stderr b/tests/ui/nll/issue-27282-move-match-input-into-guard.stderr index 4df53c0673f2c..a52dbdbf23a6b 100644 --- a/tests/ui/nll/issue-27282-move-match-input-into-guard.stderr +++ b/tests/ui/nll/issue-27282-move-match-input-into-guard.stderr @@ -1,29 +1,27 @@ -error[E0382]: use of moved value: `b` - --> $DIR/issue-27282-move-match-input-into-guard.rs:12:5 +error[E0510]: cannot mutably borrow `*b` in match guard + --> $DIR/issue-27282-move-match-input-into-guard.rs:15:14 | -LL | let b = &mut true; - | - move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait LL | match b { - | ^^^^^^^ value used here after move + | - value is immutable in match guard ... -LL | _ if { (|| { let bar = b; *bar = false; })(); - | -- - variable moved due to use in closure - | | - | value moved into closure here +LL | (|| { + | ^^ cannot mutably borrow +LL | +LL | let bar = b; + | - borrow occurs due to use of `*b` in closure -error[E0382]: use of moved value: `b` - --> $DIR/issue-27282-move-match-input-into-guard.rs:22:5 +error[E0510]: cannot mutably borrow `*b` in match guard + --> $DIR/issue-27282-move-match-input-into-guard.rs:32:14 | -LL | let b = &mut true; - | - move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait LL | match b { - | ^^^^^^^ value used here after move + | - value is immutable in match guard ... -LL | (|| { let bar = b; *bar = false; })(); - | -- - variable moved due to use in closure - | | - | value moved into closure here +LL | (|| { + | ^^ cannot mutably borrow +LL | +LL | let bar = b; + | - borrow occurs due to use of `*b` in closure error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0382`. +For more information about this error, try `rustc --explain E0510`. diff --git a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs index 5af258c3a6c36..d2081aebb4c2a 100644 --- a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs +++ b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.rs @@ -7,7 +7,7 @@ fn main() { None => {}, ref mut foo if { (|| { let mut bar = foo; bar.take() })(); false } => {}, - //~^ ERROR cannot move out of `foo` in pattern guard [E0507] + //~^ ERROR cannot borrow `*foo` as mutable, as it is immutable for the pattern guard [E0596] Some(s) => std::process::exit(*s), } @@ -15,7 +15,7 @@ fn main() { None => {}, ref mut foo if let Some(()) = { (|| { let mut bar = foo; bar.take() })(); None } => {}, - //~^ ERROR cannot move out of `foo` in pattern guard [E0507] + //~^ ERROR cannot borrow `*foo` as mutable, as it is immutable for the pattern guard [E0596] Some(s) => std::process::exit(*s), } } diff --git a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr index 0f1f2b83c42d1..1794300186f02 100644 --- a/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr +++ b/tests/ui/nll/issue-27282-move-ref-mut-into-guard.stderr @@ -1,23 +1,23 @@ -error[E0507]: cannot move out of `foo` in pattern guard +error[E0596]: cannot borrow `*foo` as mutable, as it is immutable for the pattern guard --> $DIR/issue-27282-move-ref-mut-into-guard.rs:9:19 | LL | if { (|| { let mut bar = foo; bar.take() })(); false } => {}, - | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait + | ^^ --- mutable borrow occurs due to use of `*foo` in closure | | - | `foo` is moved here + | cannot borrow as mutable | - = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + = note: variables bound in patterns are immutable until the end of the pattern guard -error[E0507]: cannot move out of `foo` in pattern guard +error[E0596]: cannot borrow `*foo` as mutable, as it is immutable for the pattern guard --> $DIR/issue-27282-move-ref-mut-into-guard.rs:17:34 | LL | if let Some(()) = { (|| { let mut bar = foo; bar.take() })(); None } => {}, - | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait + | ^^ --- mutable borrow occurs due to use of `*foo` in closure | | - | `foo` is moved here + | cannot borrow as mutable | - = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + = note: variables bound in patterns are immutable until the end of the pattern guard error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0507`. +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/nll/issue-27282-mutation-in-guard.rs b/tests/ui/nll/issue-27282-mutation-in-guard.rs index a37b4f3fc1468..1a96ef4b20ed9 100644 --- a/tests/ui/nll/issue-27282-mutation-in-guard.rs +++ b/tests/ui/nll/issue-27282-mutation-in-guard.rs @@ -4,7 +4,7 @@ fn main() { ref mut foo if { (|| { let bar = foo; bar.take() })(); - //~^ ERROR cannot move out of `foo` in pattern guard + //~^ ERROR cannot borrow `*foo` as mutable, as it is immutable for the pattern guard false } => {}, Some(ref _s) => println!("Note this arm is bogus; the `Some` became `None` in the guard."), @@ -16,7 +16,7 @@ fn main() { ref mut foo if let Some(()) = { (|| { let bar = foo; bar.take() })(); - //~^ ERROR cannot move out of `foo` in pattern guard + //~^ ERROR cannot borrow `*foo` as mutable, as it is immutable for the pattern guard None } => {}, Some(_) => {}, diff --git a/tests/ui/nll/issue-27282-mutation-in-guard.stderr b/tests/ui/nll/issue-27282-mutation-in-guard.stderr index bd531eb6d0199..e12b6d5ad1e63 100644 --- a/tests/ui/nll/issue-27282-mutation-in-guard.stderr +++ b/tests/ui/nll/issue-27282-mutation-in-guard.stderr @@ -1,23 +1,23 @@ -error[E0507]: cannot move out of `foo` in pattern guard +error[E0596]: cannot borrow `*foo` as mutable, as it is immutable for the pattern guard --> $DIR/issue-27282-mutation-in-guard.rs:6:18 | LL | (|| { let bar = foo; bar.take() })(); - | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait + | ^^ --- mutable borrow occurs due to use of `*foo` in closure | | - | `foo` is moved here + | cannot borrow as mutable | - = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + = note: variables bound in patterns are immutable until the end of the pattern guard -error[E0507]: cannot move out of `foo` in pattern guard +error[E0596]: cannot borrow `*foo` as mutable, as it is immutable for the pattern guard --> $DIR/issue-27282-mutation-in-guard.rs:18:18 | LL | (|| { let bar = foo; bar.take() })(); - | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait + | ^^ --- mutable borrow occurs due to use of `*foo` in closure | | - | `foo` is moved here + | cannot borrow as mutable | - = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + = note: variables bound in patterns are immutable until the end of the pattern guard error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0507`. +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs b/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs index 7ea1c445d143e..52bea5b475253 100644 --- a/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs +++ b/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs @@ -25,6 +25,6 @@ fn finish_3(s: S) -> &mut String { fn finish_4(s: S) -> &mut String { let p = s.url; p } -//~^^ ERROR cannot move out of type `S<'_>`, which implements the `Drop` trait +//~^^ ERROR borrow may still be in use when destructor runs [E0713] fn main() {} diff --git a/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr b/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr index 7f9cbc3c30a92..a56e2ac04880a 100644 --- a/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr +++ b/tests/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.stderr @@ -28,21 +28,16 @@ LL | let p: &mut _ = s.url; p LL | } | - here, drop of `s` needs exclusive access to `*s.url`, because the type `S<'_>` implements the `Drop` trait -error[E0509]: cannot move out of type `S<'_>`, which implements the `Drop` trait +error[E0713]: borrow may still be in use when destructor runs --> $DIR/issue-52059-report-when-borrow-and-drop-conflict.rs:26:13 | +LL | fn finish_4(s: S) -> &mut String { + | - has type `S<'1>` LL | let p = s.url; p - | ^^^^^ - | | - | cannot move out of here - | move occurs because `s.url` has type `&mut String`, which does not implement the `Copy` trait - | -help: consider borrowing here - | -LL | let p = &s.url; p - | + + | ^^^^^ - returning this value requires that `*s.url` is borrowed for `'1` +LL | } + | - here, drop of `s` needs exclusive access to `*s.url`, because the type `S<'_>` implements the `Drop` trait error: aborting due to 4 previous errors -Some errors have detailed explanations: E0509, E0713. -For more information about an error, try `rustc --explain E0509`. +For more information about this error, try `rustc --explain E0713`. diff --git a/tests/ui/nll/match-guards-always-borrow.rs b/tests/ui/nll/match-guards-always-borrow.rs index c8aa9686156c8..2fa48a03aec9f 100644 --- a/tests/ui/nll/match-guards-always-borrow.rs +++ b/tests/ui/nll/match-guards-always-borrow.rs @@ -8,7 +8,7 @@ fn should_reject_destructive_mutate_in_guard() { None => {}, ref mut foo if { (|| { let mut bar = foo; bar.take() })(); - //~^ ERROR cannot move out of `foo` in pattern guard [E0507] + //~^ ERROR cannot borrow `*foo` as mutable, as it is immutable for the pattern guard [E0596] false } => { }, Some(s) => std::process::exit(*s), } @@ -17,7 +17,7 @@ fn should_reject_destructive_mutate_in_guard() { None => {}, ref mut foo if let Some(()) = { (|| { let mut bar = foo; bar.take() })(); - //~^ ERROR cannot move out of `foo` in pattern guard [E0507] + //~^ ERROR cannot borrow `*foo` as mutable, as it is immutable for the pattern guard [E0596] None } => { }, Some(s) => std::process::exit(*s), } diff --git a/tests/ui/nll/match-guards-always-borrow.stderr b/tests/ui/nll/match-guards-always-borrow.stderr index e48e5224c6fbb..d9238727d0343 100644 --- a/tests/ui/nll/match-guards-always-borrow.stderr +++ b/tests/ui/nll/match-guards-always-borrow.stderr @@ -1,23 +1,23 @@ -error[E0507]: cannot move out of `foo` in pattern guard +error[E0596]: cannot borrow `*foo` as mutable, as it is immutable for the pattern guard --> $DIR/match-guards-always-borrow.rs:10:14 | LL | (|| { let mut bar = foo; bar.take() })(); - | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait + | ^^ --- mutable borrow occurs due to use of `*foo` in closure | | - | `foo` is moved here + | cannot borrow as mutable | - = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + = note: variables bound in patterns are immutable until the end of the pattern guard -error[E0507]: cannot move out of `foo` in pattern guard +error[E0596]: cannot borrow `*foo` as mutable, as it is immutable for the pattern guard --> $DIR/match-guards-always-borrow.rs:19:14 | LL | (|| { let mut bar = foo; bar.take() })(); - | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait + | ^^ --- mutable borrow occurs due to use of `*foo` in closure | | - | `foo` is moved here + | cannot borrow as mutable | - = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + = note: variables bound in patterns are immutable until the end of the pattern guard error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0507`. +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/nll/polonius/nll-problem-case-3-issue-68934.nll.stderr b/tests/ui/nll/polonius/nll-problem-case-3-issue-68934.nll.stderr index 067b3f21a957d..55bbb98e643ab 100644 --- a/tests/ui/nll/polonius/nll-problem-case-3-issue-68934.nll.stderr +++ b/tests/ui/nll/polonius/nll-problem-case-3-issue-68934.nll.stderr @@ -1,17 +1,17 @@ -error[E0505]: cannot move out of value because it is borrowed +error[E0499]: cannot borrow value as mutable more than once at a time --> $DIR/nll-problem-case-3-issue-68934.rs:36:14 | LL | fn deep_fetch(&mut self, value: Either) -> Result<&mut Self, (&mut Self, Either)> { | - let's call the lifetime of this reference `'1` LL | match (self, value) { LL | (Tree::ABranch(ref mut a, ref v), Either::Left(vv)) if v > &vv => { - | --------- borrow of value occurs here + | --------- first mutable borrow occurs here LL | a.deep_fetch(Either::Left(vv)) - | ------------------------------ returning this value requires that borrow lasts for `'1` + | ------------------------------ returning this value requires that first borrow lasts for `'1` ... LL | (this, _v) => Err((this, _v)), - | ^^^^ move out of value occurs here + | ^^^^ second mutable borrow occurs here error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0505`. +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/nll/polonius/polonius-smoke-test.legacy.stderr b/tests/ui/nll/polonius/polonius-smoke-test.legacy.stderr index 1268f6167f855..3af5d439fb3bb 100644 --- a/tests/ui/nll/polonius/polonius-smoke-test.legacy.stderr +++ b/tests/ui/nll/polonius/polonius-smoke-test.legacy.stderr @@ -14,46 +14,30 @@ LL | let z = x; LL | let w = y; | - borrow later used here -error[E0505]: cannot move out of `x` because it is borrowed +error[E0499]: cannot borrow `*x` as mutable more than once at a time --> $DIR/polonius-smoke-test.rs:22:13 | LL | pub fn use_while_mut_fr(x: &mut i32) -> &mut i32 { - | - - let's call the lifetime of this reference `'1` - | | - | binding `x` declared here + | - let's call the lifetime of this reference `'1` LL | let y = &mut *x; - | ------- borrow of `*x` occurs here + | ------- first mutable borrow occurs here LL | let z = x; - | ^ move out of `x` occurs here + | ^ second mutable borrow occurs here LL | y | - returning this value requires that `*x` is borrowed for `'1` - | -help: consider cloning the value if the performance cost is acceptable - | -LL - let y = &mut *x; -LL + let y = &mut x.clone(); - | -error[E0505]: cannot move out of `s` because it is borrowed +error[E0499]: cannot borrow `*s` as mutable more than once at a time --> $DIR/polonius-smoke-test.rs:46:5 | -LL | let s = &mut 1; - | - binding `s` declared here LL | let r = &mut *s; - | ------- borrow of `*s` occurs here + | ------- first mutable borrow occurs here LL | let tmp = foo(&r); LL | s; - | ^ move out of `s` occurs here + | ^ second mutable borrow occurs here LL | tmp; - | --- borrow later used here - | -help: consider cloning the value if the performance cost is acceptable - | -LL - let r = &mut *s; -LL + let r = &mut s.clone(); - | + | --- first borrow later used here error: aborting due to 4 previous errors -Some errors have detailed explanations: E0503, E0505, E0515. -For more information about an error, try `rustc --explain E0503`. +Some errors have detailed explanations: E0499, E0503, E0515. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/nll/polonius/polonius-smoke-test.polonius.stderr b/tests/ui/nll/polonius/polonius-smoke-test.polonius.stderr index 1268f6167f855..3af5d439fb3bb 100644 --- a/tests/ui/nll/polonius/polonius-smoke-test.polonius.stderr +++ b/tests/ui/nll/polonius/polonius-smoke-test.polonius.stderr @@ -14,46 +14,30 @@ LL | let z = x; LL | let w = y; | - borrow later used here -error[E0505]: cannot move out of `x` because it is borrowed +error[E0499]: cannot borrow `*x` as mutable more than once at a time --> $DIR/polonius-smoke-test.rs:22:13 | LL | pub fn use_while_mut_fr(x: &mut i32) -> &mut i32 { - | - - let's call the lifetime of this reference `'1` - | | - | binding `x` declared here + | - let's call the lifetime of this reference `'1` LL | let y = &mut *x; - | ------- borrow of `*x` occurs here + | ------- first mutable borrow occurs here LL | let z = x; - | ^ move out of `x` occurs here + | ^ second mutable borrow occurs here LL | y | - returning this value requires that `*x` is borrowed for `'1` - | -help: consider cloning the value if the performance cost is acceptable - | -LL - let y = &mut *x; -LL + let y = &mut x.clone(); - | -error[E0505]: cannot move out of `s` because it is borrowed +error[E0499]: cannot borrow `*s` as mutable more than once at a time --> $DIR/polonius-smoke-test.rs:46:5 | -LL | let s = &mut 1; - | - binding `s` declared here LL | let r = &mut *s; - | ------- borrow of `*s` occurs here + | ------- first mutable borrow occurs here LL | let tmp = foo(&r); LL | s; - | ^ move out of `s` occurs here + | ^ second mutable borrow occurs here LL | tmp; - | --- borrow later used here - | -help: consider cloning the value if the performance cost is acceptable - | -LL - let r = &mut *s; -LL + let r = &mut s.clone(); - | + | --- first borrow later used here error: aborting due to 4 previous errors -Some errors have detailed explanations: E0503, E0505, E0515. -For more information about an error, try `rustc --explain E0503`. +Some errors have detailed explanations: E0499, E0503, E0515. +For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs index 98f316dd74bdd..570ef90ece4ac 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs @@ -105,16 +105,14 @@ fn main() { //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable - //~| ERROR cannot move out of `b` in pattern guard - //~| ERROR cannot move out of `b` in pattern guard + //~| ERROR cannot borrow `*b` as mutable, as it is immutable for the pattern guard [E0596] _ => {} } match Ok(U) { ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable - //~| ERROR cannot move out of `a` in pattern guard - //~| ERROR cannot move out of `a` in pattern guard + //~| ERROR cannot borrow `*a` as mutable, as it is immutable for the pattern guard [E0596] _ => {} } diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr index 9359244c6ebc1..8d5cf3f44d115 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr @@ -170,7 +170,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false | value is borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:112:9 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ^^^^^^^^^ ----- value is borrowed by `b` here @@ -178,7 +178,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false | value is mutably borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:33 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:112:33 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ^^^^^^^^^ ----- value is borrowed by `b` here @@ -186,7 +186,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false | value is mutably borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:119:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- --------- value is mutably borrowed by `c` here @@ -195,7 +195,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:125:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- --------- value is mutably borrowed by `c` here @@ -204,7 +204,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:133:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- --------- value is mutably borrowed by `c` here @@ -213,7 +213,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); | value is borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:138:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:136:9 | LL | let ref mut a @ (ref b, ref c) = (U, U); | ^^^^^^^^^ ----- ----- value is borrowed by `c` here @@ -326,42 +326,24 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false | | mutable borrow occurs here | immutable borrow occurs here -error[E0507]: cannot move out of `b` in pattern guard +error[E0596]: cannot borrow `*b` as mutable, as it is immutable for the pattern guard --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} - | ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait + | ^ cannot borrow as mutable | - = note: variables bound in patterns cannot be moved from until after the end of the pattern guard - -error[E0507]: cannot move out of `b` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66 - | -LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} - | ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait - | - = note: variables bound in patterns cannot be moved from until after the end of the pattern guard - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0507]: cannot move out of `a` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:66 - | -LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} - | ^ move occurs because `a` has type `&mut Result`, which does not implement the `Copy` trait - | - = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + = note: variables bound in patterns are immutable until the end of the pattern guard -error[E0507]: cannot move out of `a` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:66 +error[E0596]: cannot borrow `*a` as mutable, as it is immutable for the pattern guard + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:112:66 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} - | ^ move occurs because `a` has type `&mut Result`, which does not implement the `Copy` trait + | ^ cannot borrow as mutable | - = note: variables bound in patterns cannot be moved from until after the end of the pattern guard - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = note: variables bound in patterns are immutable until the end of the pattern guard error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:119:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- mutable borrow occurs here @@ -372,7 +354,7 @@ LL | *b = U; | ------ mutable borrow later used here error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:125:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- mutable borrow occurs here @@ -383,7 +365,7 @@ LL | *b = U; | ------ mutable borrow later used here error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:133:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- mutable borrow occurs here @@ -443,7 +425,7 @@ LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {} | | value borrowed here after move | move occurs because value has type `U`, which does not implement the `Copy` trait -error: aborting due to 51 previous errors +error: aborting due to 49 previous errors -Some errors have detailed explanations: E0382, E0502, E0507, E0594. +Some errors have detailed explanations: E0382, E0502, E0594, E0596. For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2021.stderr index ba1654c64d928..6b17f9509f9d5 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2021.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2021.stderr @@ -1,19 +1,13 @@ -error[E0507]: cannot move out of a shared reference - --> $DIR/borrowck-errors.rs:33:29 +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/borrowck-errors.rs:32:23 | LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { - | - ^^^^^^^^^^^^^^^^^^^ + | ^ ------------------- this cannot be borrowed as mutable | | - | data moved here because `x` has type `&mut u32`, which does not implement the `Copy` trait - | -help: consider removing the borrow - | -LL - if let Some(&Some(x)) = Some(&Some(&mut 0)) { -LL + if let Some(Some(x)) = Some(&Some(&mut 0)) { - | + | cannot borrow as mutable error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/borrowck-errors.rs:38:10 + --> $DIR/borrowck-errors.rs:37:10 | LL | let &ref mut x = &0; | ^^^^^^^^^ -- this cannot be borrowed as mutable @@ -21,7 +15,7 @@ LL | let &ref mut x = &0; | cannot borrow as mutable error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/borrowck-errors.rs:43:23 + --> $DIR/borrowck-errors.rs:42:23 | LL | if let &Some(Some(x)) = &Some(&mut Some(0)) { | ^ ------------------- this cannot be borrowed as mutable @@ -29,7 +23,7 @@ LL | if let &Some(Some(x)) = &Some(&mut Some(0)) { | cannot borrow as mutable error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/borrowck-errors.rs:48:11 + --> $DIR/borrowck-errors.rs:47:11 | LL | let &[x] = &&mut [0]; | ^ --------- this cannot be borrowed as mutable @@ -38,5 +32,4 @@ LL | let &[x] = &&mut [0]; error: aborting due to 4 previous errors -Some errors have detailed explanations: E0507, E0596. -For more information about an error, try `rustc --explain E0507`. +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr index 102d44e7b523b..743e99fbaba57 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr @@ -1,45 +1,19 @@ -error[E0508]: cannot move out of type `[&mut i32; 1]`, a non-copy array - --> $DIR/borrowck-errors.rs:17:16 +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/borrowck-errors.rs:17:11 | LL | let [&x] = &[&mut 0]; - | - ^^^^^^^^^ cannot move out of here - | | - | data moved here because `x` has type `&mut i32`, which does not implement the `Copy` trait - | -help: consider borrowing the pattern binding - | -LL | let [&ref x] = &[&mut 0]; - | +++ - -error[E0508]: cannot move out of type `[&mut i32; 1]`, a non-copy array - --> $DIR/borrowck-errors.rs:24:16 - | -LL | let [&x] = &mut [&mut 0]; - | - ^^^^^^^^^^^^^ cannot move out of here + | ^ --------- this cannot be borrowed as mutable | | - | data moved here because `x` has type `&mut i32`, which does not implement the `Copy` trait - | -help: consider borrowing the pattern binding - | -LL | let [&ref x] = &mut [&mut 0]; - | +++ + | cannot borrow as mutable -error[E0507]: cannot move out of a shared reference - --> $DIR/borrowck-errors.rs:33:29 +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/borrowck-errors.rs:32:23 | LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { - | - ^^^^^^^^^^^^^^^^^^^ - | | - | data moved here because `x` has type `&mut u32`, which does not implement the `Copy` trait - | -help: consider removing the borrow - | -LL - if let Some(&Some(x)) = Some(&Some(&mut 0)) { -LL + if let Some(Some(x)) = Some(&Some(&mut 0)) { - | + | ^ cannot borrow as mutable error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/borrowck-errors.rs:38:10 + --> $DIR/borrowck-errors.rs:37:10 | LL | let &ref mut x = &0; | ^^^^^^^^^ -- this cannot be borrowed as mutable @@ -47,33 +21,19 @@ LL | let &ref mut x = &0; | cannot borrow as mutable error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/borrowck-errors.rs:43:23 + --> $DIR/borrowck-errors.rs:42:23 | LL | if let &Some(Some(x)) = &Some(&mut Some(0)) { | ^ cannot borrow as mutable error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/borrowck-errors.rs:48:11 + --> $DIR/borrowck-errors.rs:47:11 | LL | let &[x] = &&mut [0]; | ^ --------- this cannot be borrowed as mutable | | | cannot borrow as mutable -error[E0508]: cannot move out of type `[&mut i32; 1]`, a non-copy array - --> $DIR/borrowck-errors.rs:52:20 - | -LL | let [&mut x] = &mut [&mut 0]; - | - ^^^^^^^^^^^^^ cannot move out of here - | | - | data moved here because `x` has type `&mut i32`, which does not implement the `Copy` trait - | -help: consider borrowing the pattern binding - | -LL | let [&mut ref x] = &mut [&mut 0]; - | +++ - -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0507, E0508, E0596. -For more information about an error, try `rustc --explain E0507`. +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs index 15575510e1651..9b55ec392430c 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs @@ -17,21 +17,20 @@ fn errors_caught_in_hir_typeck_on_stable() { let [&x] = &[&mut 0]; //[stable2021]~^ ERROR mismatched types //[stable2021]~| NOTE types differ in mutability - //[classic2024]~^^^ ERROR: cannot move out of type + //[classic2024]~^^^ ERROR: cannot borrow data in a `&` reference as mutable [E0596] #[cfg(any(classic2021, structural2021))] let _: u32 = x; #[cfg(structural2024)] let _: &u32 = x; let [&x] = &mut [&mut 0]; //[stable2021]~^ ERROR mismatched types //[stable2021]~| NOTE types differ in mutability - //[classic2024]~^^^ ERROR: cannot move out of type #[cfg(any(classic2021, structural2021))] let _: u32 = x; #[cfg(structural2024)] let _: &u32 = x; } pub fn main() { if let Some(&Some(x)) = Some(&Some(&mut 0)) { - //~^ ERROR: cannot move out of a shared reference [E0507] + //~^ ERROR: cannot borrow data in a `&` reference as mutable [E0596] let _: &u32 = x; } @@ -50,7 +49,6 @@ pub fn main() { #[cfg(any(structural2021, structural2024))] let _: &u32 = x; let [&mut x] = &mut [&mut 0]; - //[classic2024]~^ ERROR: cannot move out of type #[cfg(any(stable2021, classic2021, structural2021))] let _: u32 = x; #[cfg(structural2024)] let _: &mut u32 = x; } diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr index f9e61394cb519..ad062e4bda6fa 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr @@ -30,22 +30,16 @@ LL - let [&x] = &mut [&mut 0]; LL + let [x] = &mut [&mut 0]; | -error[E0507]: cannot move out of a shared reference - --> $DIR/borrowck-errors.rs:33:29 +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/borrowck-errors.rs:32:23 | LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { - | - ^^^^^^^^^^^^^^^^^^^ + | ^ ------------------- this cannot be borrowed as mutable | | - | data moved here because `x` has type `&mut u32`, which does not implement the `Copy` trait - | -help: consider removing the borrow - | -LL - if let Some(&Some(x)) = Some(&Some(&mut 0)) { -LL + if let Some(Some(x)) = Some(&Some(&mut 0)) { - | + | cannot borrow as mutable error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/borrowck-errors.rs:38:10 + --> $DIR/borrowck-errors.rs:37:10 | LL | let &ref mut x = &0; | ^^^^^^^^^ -- this cannot be borrowed as mutable @@ -53,7 +47,7 @@ LL | let &ref mut x = &0; | cannot borrow as mutable error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/borrowck-errors.rs:43:23 + --> $DIR/borrowck-errors.rs:42:23 | LL | if let &Some(Some(x)) = &Some(&mut Some(0)) { | ^ ------------------- this cannot be borrowed as mutable @@ -61,7 +55,7 @@ LL | if let &Some(Some(x)) = &Some(&mut Some(0)) { | cannot borrow as mutable error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/borrowck-errors.rs:48:11 + --> $DIR/borrowck-errors.rs:47:11 | LL | let &[x] = &&mut [0]; | ^ --------- this cannot be borrowed as mutable @@ -70,5 +64,5 @@ LL | let &[x] = &&mut [0]; error: aborting due to 6 previous errors -Some errors have detailed explanations: E0308, E0507, E0596. +Some errors have detailed explanations: E0308, E0596. For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2021.stderr index ac53c0dc89f83..713edd1904728 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2021.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2021.stderr @@ -1,19 +1,13 @@ -error[E0507]: cannot move out of a shared reference - --> $DIR/borrowck-errors.rs:33:29 +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/borrowck-errors.rs:32:23 | LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { - | - ^^^^^^^^^^^^^^^^^^^ + | ^ ------------------- this cannot be borrowed as mutable | | - | data moved here because `x` has type `&mut u32`, which does not implement the `Copy` trait - | -help: consider removing the borrow - | -LL - if let Some(&Some(x)) = Some(&Some(&mut 0)) { -LL + if let Some(Some(x)) = Some(&Some(&mut 0)) { - | + | cannot borrow as mutable error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/borrowck-errors.rs:38:10 + --> $DIR/borrowck-errors.rs:37:10 | LL | let &ref mut x = &0; | ^^^^^^^^^ -- this cannot be borrowed as mutable @@ -22,5 +16,4 @@ LL | let &ref mut x = &0; error: aborting due to 2 previous errors -Some errors have detailed explanations: E0507, E0596. -For more information about an error, try `rustc --explain E0507`. +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr index ac53c0dc89f83..5af74bac5b667 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr @@ -1,19 +1,11 @@ -error[E0507]: cannot move out of a shared reference - --> $DIR/borrowck-errors.rs:33:29 +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/borrowck-errors.rs:32:23 | LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) { - | - ^^^^^^^^^^^^^^^^^^^ - | | - | data moved here because `x` has type `&mut u32`, which does not implement the `Copy` trait - | -help: consider removing the borrow - | -LL - if let Some(&Some(x)) = Some(&Some(&mut 0)) { -LL + if let Some(Some(x)) = Some(&Some(&mut 0)) { - | + | ^ cannot borrow as mutable error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/borrowck-errors.rs:38:10 + --> $DIR/borrowck-errors.rs:37:10 | LL | let &ref mut x = &0; | ^^^^^^^^^ -- this cannot be borrowed as mutable @@ -22,5 +14,4 @@ LL | let &ref mut x = &0; error: aborting due to 2 previous errors -Some errors have detailed explanations: E0507, E0596. -For more information about an error, try `rustc --explain E0507`. +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/reborrow/mut-autoreborrow-fail.rs b/tests/ui/reborrow/mut-autoreborrow-fail.rs new file mode 100644 index 0000000000000..56ab4a099afb7 --- /dev/null +++ b/tests/ui/reborrow/mut-autoreborrow-fail.rs @@ -0,0 +1,14 @@ +// Known bug: ideally, this would compile. + +fn assert_fnmut(_: &mut impl FnMut()) {} + +fn main() { + let x = &mut Box::new(0); + let mut f = || { + //~^ ERROR expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce` [E0525] + let _y = x; + }; + f(); + f(); + assert_fnmut(&mut f); +} diff --git a/tests/ui/reborrow/mut-autoreborrow-fail.stderr b/tests/ui/reborrow/mut-autoreborrow-fail.stderr new file mode 100644 index 0000000000000..a46bc63134e0a --- /dev/null +++ b/tests/ui/reborrow/mut-autoreborrow-fail.stderr @@ -0,0 +1,23 @@ +error[E0525]: expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce` + --> $DIR/mut-autoreborrow-fail.rs:7:17 + | +LL | let mut f = || { + | ^^ this closure implements `FnOnce`, not `FnMut` +LL | +LL | let _y = x; + | - closure is `FnOnce` because it moves the variable `x` out of its environment +... +LL | assert_fnmut(&mut f); + | ------------ ------ the requirement to implement `FnMut` derives from here + | | + | required by a bound introduced by this call + | +note: required by a bound in `assert_fnmut` + --> $DIR/mut-autoreborrow-fail.rs:3:30 + | +LL | fn assert_fnmut(_: &mut impl FnMut()) {} + | ^^^^^^^ required by this bound in `assert_fnmut` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0525`. diff --git a/tests/ui/try-block/try-block-bad-lifetime.rs b/tests/ui/try-block/try-block-bad-lifetime.rs index 9b45b0d955947..fb3b6b95d5bd7 100644 --- a/tests/ui/try-block/try-block-bad-lifetime.rs +++ b/tests/ui/try-block/try-block-bad-lifetime.rs @@ -28,7 +28,7 @@ pub fn main() { Err(k) ?; i = 10; //~ ERROR cannot assign to `i` because it is borrowed }; - ::std::mem::drop(k); //~ ERROR use of moved value: `k` + ::std::mem::drop(k); //~ ERROR cannot borrow `*k` as mutable more than once at a time [E0499] i = 40; //~ ERROR cannot assign to `i` because it is borrowed let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") }; diff --git a/tests/ui/try-block/try-block-bad-lifetime.stderr b/tests/ui/try-block/try-block-bad-lifetime.stderr index 28941cb0a9e40..d5dcc6b4ddb45 100644 --- a/tests/ui/try-block/try-block-bad-lifetime.stderr +++ b/tests/ui/try-block/try-block-bad-lifetime.stderr @@ -23,17 +23,17 @@ LL | }; LL | ::std::mem::drop(k); | - borrow later used here -error[E0382]: use of moved value: `k` +error[E0499]: cannot borrow `*k` as mutable more than once at a time --> $DIR/try-block-bad-lifetime.rs:31:26 | -LL | let k = &mut i; - | - move occurs because `k` has type `&mut i32`, which does not implement the `Copy` trait -LL | let mut j: Result<(), &mut i32> = try { LL | Err(k) ?; - | - value moved here + | - first mutable borrow occurs here ... LL | ::std::mem::drop(k); - | ^ value used here after move + | ^ second mutable borrow occurs here +... +LL | let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") }; + | - first borrow later used here error[E0506]: cannot assign to `i` because it is borrowed --> $DIR/try-block-bad-lifetime.rs:32:9 @@ -49,5 +49,5 @@ LL | let i_ptr = if let Err(i_ptr) = j { i_ptr } else { panic ! ("") }; error: aborting due to 4 previous errors -Some errors have detailed explanations: E0382, E0506, E0597. -For more information about an error, try `rustc --explain E0382`. +Some errors have detailed explanations: E0499, E0506, E0597. +For more information about an error, try `rustc --explain E0499`. From d7a640ad6d6fb22cdd2c662b0429670139ad0579 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Wed, 30 Sep 2026 23:45:05 -0400 Subject: [PATCH 2/5] Remove reborrow suggestion diagnostics These are dead code now! --- .../src/diagnostics/conflict_errors.rs | 38 ------------------- .../rustc_borrowck/src/diagnostics/mod.rs | 31 --------------- .../src/diagnostics/move_errors.rs | 2 - 3 files changed, 71 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 2f8ff159ceb0a..ecea9b0453fbb 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -229,14 +229,12 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { is_loop_move = true; } - let mut has_suggest_reborrow = false; if !seen_spans.contains(&move_span) { self.suggest_ref_or_clone( mpi, &mut err, move_spans, moved_place.as_ref(), - &mut has_suggest_reborrow, closure, ); @@ -244,8 +242,6 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { is_partial_move, is_loop_message, is_move_msg, - is_loop_move, - has_suggest_reborrow, maybe_reinitialized_locations_is_empty: maybe_reinitialized_locations .is_empty(), }; @@ -356,7 +352,6 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { err: &mut Diag<'_>, move_spans: UseSpans<'tcx>, moved_place: PlaceRef<'tcx>, - has_suggest_reborrow: &mut bool, moved_or_invoked_closure: bool, ) { let move_span = match move_spans { @@ -477,20 +472,6 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { None }; - // If the moved value is a mut reference, it is used in a - // generic function and it's type is a generic param, it can be - // reborrowed to avoid moving. - // for example: - // struct Y(u32); - // x's type is '& mut Y' and it is used in `fn generic(x: T) {}`. - if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() - && arg_param.is_some() - { - *has_suggest_reborrow = true; - self.suggest_reborrow(err, expr.span, moved_place); - return; - } - // If the moved place is used generically by the callee and a reference to it // would still satisfy any bounds on its type, suggest borrowing. if let Some(¶m) = arg_param @@ -632,25 +613,6 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { } } - pub(crate) fn suggest_reborrow( - &self, - err: &mut Diag<'_>, - span: Span, - moved_place: PlaceRef<'tcx>, - ) { - err.span_suggestion_verbose( - span.shrink_to_lo(), - format!( - "consider creating a fresh reborrow of {} here", - self.describe_place(moved_place) - .map(|n| format!("`{n}`")) - .unwrap_or_else(|| "the mutable reference".to_string()), - ), - "&mut *", - Applicability::MachineApplicable, - ); - } - /// If a place is used after being moved as an argument to a function, the function is generic /// in that argument, and a reference to the argument's type would still satisfy the function's /// bounds, suggest borrowing. This covers, e.g., borrowing an `impl Fn()` argument being passed diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index cb60a97eea053..f2464e504ccfb 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -34,7 +34,6 @@ use tracing::debug; use super::MirBorrowckCtxt; use super::borrow_set::BorrowData; -use crate::LocalMutationIsAllowed; use crate::constraints::OutlivesConstraint; use crate::nll::ConstraintDescription; use crate::session_diagnostics::{ @@ -993,8 +992,6 @@ struct CapturedMessageOpt { is_partial_move: bool, is_loop_message: bool, is_move_msg: bool, - is_loop_move: bool, - has_suggest_reborrow: bool, maybe_reinitialized_locations_is_empty: bool, } @@ -1235,8 +1232,6 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { is_partial_move: is_partial, is_loop_message, is_move_msg, - is_loop_move, - has_suggest_reborrow, maybe_reinitialized_locations_is_empty, } = msg_opt; let mut suggested_cloning = false; @@ -1435,32 +1430,6 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { } _ => {} } - // If the moved place was a `&mut` ref, then we can - // suggest to reborrow it where it was moved, so it - // will still be valid by the time we get to the usage. - if let ty::Ref(_, _, hir::Mutability::Mut) = - moved_place.ty(self.body, self.infcx.tcx).ty.kind() - { - // The `&mut *place` reborrow suggestion is `MachineApplicable`, so - // only offer it where `*place` can be borrowed mutably: a value - // captured by an `Fn` closure (held via `&self`) cannot, and the - // suggestion would otherwise fail to compile with E0596. - let reborrow_place = self.infcx.tcx.mk_place_deref(moved_place); - let reborrow_is_valid = self - .is_mutable(reborrow_place.as_ref(), LocalMutationIsAllowed::No) - .is_ok(); - // Suggest `reborrow` in other place for following situations: - // 1. If we are in a loop this will be suggested later. - // 2. If the moved value is a mut reference, it is used in a - // generic function and the corresponding arg's type is generic param. - if !is_loop_move && !has_suggest_reborrow && reborrow_is_valid { - self.suggest_reborrow( - err, - move_span.shrink_to_lo(), - moved_place.as_ref(), - ); - } - } } else { match desugaring { Some((CallDesugaringKind::Await, _)) => { diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 4d65410455118..369e18a507d87 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -552,8 +552,6 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { is_partial_move: false, is_loop_message: false, is_move_msg: false, - is_loop_move: false, - has_suggest_reborrow: false, maybe_reinitialized_locations_is_empty: true, }; let suggested_cloning = if let Some(use_spans) = use_spans { From a3f8edcbb0a744f3775b32049ed317127027a2e2 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Fri, 2 Oct 2026 11:59:19 -0400 Subject: [PATCH 3/5] Add support for `Reborrow` trait --- compiler/rustc_mir_build/src/builder/misc.rs | 14 + compiler/rustc_trait_selection/src/infer.rs | 6 + .../custom_marker_coerce_shared_move.rs | 2 +- .../custom_marker_coerce_shared_move.stderr | 12 +- ...m_marker_coerce_shared_move_no_conflict.rs | 2 +- ...rker_coerce_shared_move_no_conflict.stderr | 12 +- tests/ui/reborrow/custom_marker_mut_self.rs | 4 +- .../ui/reborrow/custom_marker_mut_self.stderr | 12 +- tests/ui/reborrow/custom_marker_mut_self_a.rs | 4 +- .../reborrow/custom_marker_mut_self_a.stderr | 13 +- tests/ui/reborrow/custom_marker_mut_self_b.rs | 2 +- .../reborrow/custom_marker_mut_self_b.stderr | 13 +- tests/ui/reborrow/custom_mut.rs | 16 ++ tests/ui/reborrow/custom_mut_generic.rs | 33 +++ tests/ui/reborrow/custom_mut_generic.stderr | 266 ++++++++++++++++++ tests/ui/reborrow/reborrow-method-call.rs | 28 ++ 16 files changed, 395 insertions(+), 44 deletions(-) create mode 100644 tests/ui/reborrow/custom_mut_generic.rs create mode 100644 tests/ui/reborrow/custom_mut_generic.stderr create mode 100644 tests/ui/reborrow/reborrow-method-call.rs diff --git a/compiler/rustc_mir_build/src/builder/misc.rs b/compiler/rustc_mir_build/src/builder/misc.rs index 5e21a3ce806a4..6df4e18924f0e 100644 --- a/compiler/rustc_mir_build/src/builder/misc.rs +++ b/compiler/rustc_mir_build/src/builder/misc.rs @@ -84,6 +84,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ), ); Operand::Move(reborrow) + } else if tcx.features().reborrow() + && self.infcx.type_is_reborrow_modulo_regions(self.param_env, ty) + // generic `T: Reborrow` not currently supported + && ty.is_adt() + { + // Reborrow the value. + let reborrow = self.temp(ty, span); + self.cfg.push_assign( + block, + self.source_info(span), + reborrow, + Rvalue::Reborrow(ty, Mutability::Mut, place), + ); + Operand::Move(reborrow) } else { Operand::Move(place) } diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 7e1ad3234440e..a31d09b99eb22 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -36,6 +36,12 @@ impl<'tcx> InferCtxt<'tcx> { traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id) } + fn type_is_reborrow_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { + let ty = self.deeply_resolve_ignoring_regions(ty); + let reborrow_def_id = self.tcx.require_lang_item(LangItem::Reborrow, DUMMY_SP); + traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, reborrow_def_id) + } + fn type_is_clone_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { let ty = self.deeply_resolve_ignoring_regions(ty); let clone_def_id = self.tcx.require_lang_item(LangItem::Clone, DUMMY_SP); diff --git a/tests/ui/reborrow/custom_marker_coerce_shared_move.rs b/tests/ui/reborrow/custom_marker_coerce_shared_move.rs index 472efe3f37bb7..f80a36f46d1b2 100644 --- a/tests/ui/reborrow/custom_marker_coerce_shared_move.rs +++ b/tests/ui/reborrow/custom_marker_coerce_shared_move.rs @@ -21,7 +21,7 @@ fn main() { let b = method(a); let c = method(a); move_into(a); - //~^ ERROR: cannot move out of `a` because it is borrowed + //~^ ERROR: cannot borrow `a` as mutable because it is also borrowed as immutable [E0502] let _ = b; let _ = c; } diff --git a/tests/ui/reborrow/custom_marker_coerce_shared_move.stderr b/tests/ui/reborrow/custom_marker_coerce_shared_move.stderr index e39d5e28c65b0..d90a6428ff77a 100644 --- a/tests/ui/reborrow/custom_marker_coerce_shared_move.stderr +++ b/tests/ui/reborrow/custom_marker_coerce_shared_move.stderr @@ -1,17 +1,15 @@ -error[E0505]: cannot move out of `a` because it is borrowed +error[E0502]: cannot borrow `a` as mutable because it is also borrowed as immutable --> $DIR/custom_marker_coerce_shared_move.rs:23:15 | -LL | let a = CustomMarker(PhantomData); - | - binding `a` declared here LL | let b = method(a); - | - borrow of `a` occurs here + | - immutable borrow occurs here LL | let c = method(a); LL | move_into(a); | ^ | | - | move out of `a` occurs here - | borrow later used here + | mutable borrow occurs here + | immutable borrow later used here error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0505`. +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/reborrow/custom_marker_coerce_shared_move_no_conflict.rs b/tests/ui/reborrow/custom_marker_coerce_shared_move_no_conflict.rs index 8b0ab4c9df417..319a3df4b1b84 100644 --- a/tests/ui/reborrow/custom_marker_coerce_shared_move_no_conflict.rs +++ b/tests/ui/reborrow/custom_marker_coerce_shared_move_no_conflict.rs @@ -22,5 +22,5 @@ fn main() { let b = method(a); let c = method(a); move_into(a); - //~^ ERROR: cannot move out of `a` because it is borrowed + //~^ ERROR: cannot borrow `a` as mutable because it is also borrowed as immutable [E0502] } diff --git a/tests/ui/reborrow/custom_marker_coerce_shared_move_no_conflict.stderr b/tests/ui/reborrow/custom_marker_coerce_shared_move_no_conflict.stderr index 19e41ea7bbdf2..165552751f14a 100644 --- a/tests/ui/reborrow/custom_marker_coerce_shared_move_no_conflict.stderr +++ b/tests/ui/reborrow/custom_marker_coerce_shared_move_no_conflict.stderr @@ -1,17 +1,15 @@ -error[E0505]: cannot move out of `a` because it is borrowed +error[E0502]: cannot borrow `a` as mutable because it is also borrowed as immutable --> $DIR/custom_marker_coerce_shared_move_no_conflict.rs:24:15 | -LL | let a = CustomMarker(PhantomData); - | - binding `a` declared here LL | let b = method(a); - | - borrow of `a` occurs here + | - immutable borrow occurs here LL | let c = method(a); LL | move_into(a); | ^ | | - | move out of `a` occurs here - | borrow later used here + | mutable borrow occurs here + | immutable borrow later used here error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0505`. +For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/reborrow/custom_marker_mut_self.rs b/tests/ui/reborrow/custom_marker_mut_self.rs index 7dc8dd099adf7..915418b0d46f5 100644 --- a/tests/ui/reborrow/custom_marker_mut_self.rs +++ b/tests/ui/reborrow/custom_marker_mut_self.rs @@ -1,7 +1,7 @@ //! Test that reborrowing a custom marker type implementing Reborrow conflicts with moving the type. #![feature(reborrow)] -use std::marker::{Reborrow, PhantomData}; +use std::marker::{PhantomData, Reborrow}; #[derive(Reborrow)] struct CustomMarker<'a>(PhantomData<&'a ()>); @@ -13,5 +13,5 @@ fn method<'a>(_a: CustomMarker<'a>) -> &'a () { fn main() { let a = CustomMarker(PhantomData); let b = method(a); - let _ = (a, b); //~ERROR cannot move out of `a` because it is borrowed + let _ = (a, b); //~ERROR cannot borrow `a` as mutable more than once at a time [E0499] } diff --git a/tests/ui/reborrow/custom_marker_mut_self.stderr b/tests/ui/reborrow/custom_marker_mut_self.stderr index 9527b6a7fd19f..ff21577c6535a 100644 --- a/tests/ui/reborrow/custom_marker_mut_self.stderr +++ b/tests/ui/reborrow/custom_marker_mut_self.stderr @@ -1,15 +1,13 @@ -error[E0505]: cannot move out of `a` because it is borrowed +error[E0499]: cannot borrow `a` as mutable more than once at a time --> $DIR/custom_marker_mut_self.rs:16:14 | -LL | let a = CustomMarker(PhantomData); - | - binding `a` declared here LL | let b = method(a); - | - borrow of `a` occurs here + | - first mutable borrow occurs here LL | let _ = (a, b); - | ^ - borrow later used here + | ^ - first borrow later used here | | - | move out of `a` occurs here + | second mutable borrow occurs here error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0505`. +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/reborrow/custom_marker_mut_self_a.rs b/tests/ui/reborrow/custom_marker_mut_self_a.rs index 34a301e1a4c0a..56033313aa4c3 100644 --- a/tests/ui/reborrow/custom_marker_mut_self_a.rs +++ b/tests/ui/reborrow/custom_marker_mut_self_a.rs @@ -2,7 +2,7 @@ //! is immediately dropped. #![feature(reborrow)] -use std::marker::{Reborrow, PhantomData}; +use std::marker::{PhantomData, Reborrow}; #[derive(Reborrow)] struct CustomMarker<'a>(PhantomData<&'a ()>); @@ -17,5 +17,5 @@ fn main() { let _ = method(a); //~^ ERROR: cannot borrow `a` as mutable more than once at a time let _ = (a, b); - //~^ ERROR: cannot move out of `a` because it is borrowed + //~^ ERROR: cannot borrow `a` as mutable more than once at a time [E0499] } diff --git a/tests/ui/reborrow/custom_marker_mut_self_a.stderr b/tests/ui/reborrow/custom_marker_mut_self_a.stderr index 844755e9cfec9..fb3d22d65c807 100644 --- a/tests/ui/reborrow/custom_marker_mut_self_a.stderr +++ b/tests/ui/reborrow/custom_marker_mut_self_a.stderr @@ -9,20 +9,17 @@ LL | LL | let _ = (a, b); | - first borrow later used here -error[E0505]: cannot move out of `a` because it is borrowed +error[E0499]: cannot borrow `a` as mutable more than once at a time --> $DIR/custom_marker_mut_self_a.rs:19:14 | -LL | let a = CustomMarker(PhantomData); - | - binding `a` declared here LL | let b = method(a); - | - borrow of `a` occurs here + | - first mutable borrow occurs here ... LL | let _ = (a, b); - | ^ - borrow later used here + | ^ - first borrow later used here | | - | move out of `a` occurs here + | second mutable borrow occurs here error: aborting due to 2 previous errors -Some errors have detailed explanations: E0499, E0505. -For more information about an error, try `rustc --explain E0499`. +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/reborrow/custom_marker_mut_self_b.rs b/tests/ui/reborrow/custom_marker_mut_self_b.rs index 3354548b556a4..9477a5ec3072b 100644 --- a/tests/ui/reborrow/custom_marker_mut_self_b.rs +++ b/tests/ui/reborrow/custom_marker_mut_self_b.rs @@ -16,5 +16,5 @@ fn main() { let _ = method(a); let b = method(a); let _ = (a, b); - //~^ ERROR: cannot move out of `a` because it is borrowed + //~^ ERROR: cannot borrow `a` as mutable more than once at a time [E0499] } diff --git a/tests/ui/reborrow/custom_marker_mut_self_b.stderr b/tests/ui/reborrow/custom_marker_mut_self_b.stderr index a7ecd42dbf062..9493490d67947 100644 --- a/tests/ui/reborrow/custom_marker_mut_self_b.stderr +++ b/tests/ui/reborrow/custom_marker_mut_self_b.stderr @@ -1,16 +1,13 @@ -error[E0505]: cannot move out of `a` because it is borrowed +error[E0499]: cannot borrow `a` as mutable more than once at a time --> $DIR/custom_marker_mut_self_b.rs:18:14 | -LL | let a = CustomMarker(PhantomData); - | - binding `a` declared here -LL | let _ = method(a); LL | let b = method(a); - | - borrow of `a` occurs here + | - first mutable borrow occurs here LL | let _ = (a, b); - | ^ - borrow later used here + | ^ - first borrow later used here | | - | move out of `a` occurs here + | second mutable borrow occurs here error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0505`. +For more information about this error, try `rustc --explain E0499`. diff --git a/tests/ui/reborrow/custom_mut.rs b/tests/ui/reborrow/custom_mut.rs index d712b60574c33..2312bd2a1ce4d 100644 --- a/tests/ui/reborrow/custom_mut.rs +++ b/tests/ui/reborrow/custom_mut.rs @@ -12,8 +12,24 @@ impl<'a, T> Reborrow for CustomMut<'a, T> {} fn method(_: CustomMut<'_, ()>) {} +fn generic(_: impl Sized) {} + fn main() { let a = CustomMut(&mut ()); let _ = method(a); let _ = method(a); + + generic(a); + generic(a); + { + a + }; + generic(a); + let _local = a; + generic(a); + let _ = || a; + generic(a); + let mut _tup: (CustomMut<'_, ()>,) = (CustomMut(&mut ()),); + _tup.0 = a; + generic(a); } diff --git a/tests/ui/reborrow/custom_mut_generic.rs b/tests/ui/reborrow/custom_mut_generic.rs new file mode 100644 index 0000000000000..73dff7e121df4 --- /dev/null +++ b/tests/ui/reborrow/custom_mut_generic.rs @@ -0,0 +1,33 @@ +//! A generic parameter implementing Reborrow cannot currently +//! be reborrowed multiple times. + +#![feature(reborrow)] +use std::marker::Reborrow; + +#[allow(unused)] +struct CustomMut<'a, T>(&'a mut T); +impl<'a, T> Reborrow for CustomMut<'a, T> {} + +fn method(_: impl Reborrow) {} + +fn generic(_: impl Sized) {} + +fn generic_reborrow(a: impl Reborrow) { + let _ = method(a); + let _ = method(a); //~ ERROR use of moved value + + generic(a); //~ ERROR use of moved value + generic(a); //~ ERROR use of moved value + { + a //~ ERROR use of moved value + }; + generic(a); //~ ERROR use of moved value + let _local = a; //~ ERROR use of moved value + generic(a); //~ ERROR use of moved value + let _ = || a; //~ ERROR use of moved value + generic(a); //~ ERROR use of moved value +} + +fn main() { + generic_reborrow(CustomMut(&mut ())); +} diff --git a/tests/ui/reborrow/custom_mut_generic.stderr b/tests/ui/reborrow/custom_mut_generic.stderr new file mode 100644 index 0000000000000..e3b40d564cdc3 --- /dev/null +++ b/tests/ui/reborrow/custom_mut_generic.stderr @@ -0,0 +1,266 @@ +error[E0382]: use of moved value: `a` + --> $DIR/custom_mut_generic.rs:17:20 + | +LL | fn generic_reborrow(a: impl Reborrow) { + | - move occurs because `a` has type `impl Reborrow`, which does not implement the `Copy` trait +LL | let _ = method(a); + | - value moved here +LL | let _ = method(a); + | ^ value used here after move + | +note: consider changing this parameter type in function `method` to borrow instead if owning the value isn't necessary + --> $DIR/custom_mut_generic.rs:11:14 + | +LL | fn method(_: impl Reborrow) {} + | ------ ^^^^^^^^^^^^^ this parameter takes ownership of the value + | | + | in this function +help: if `impl Reborrow` implemented `Clone`, you could clone the value + --> $DIR/custom_mut_generic.rs:15:24 + | +LL | fn generic_reborrow(a: impl Reborrow) { + | ^^^^^^^^^^^^^ consider constraining this type parameter with `Clone` +LL | let _ = method(a); + | - you could clone this value +help: consider restricting opaque type `impl Reborrow` with trait `Copy` + | +LL | fn generic_reborrow(a: impl Reborrow + Copy) { + | ++++++ + +error[E0382]: use of moved value: `a` + --> $DIR/custom_mut_generic.rs:19:13 + | +LL | fn generic_reborrow(a: impl Reborrow) { + | - move occurs because `a` has type `impl Reborrow`, which does not implement the `Copy` trait +LL | let _ = method(a); +LL | let _ = method(a); + | - value moved here +LL | +LL | generic(a); + | ^ value used here after move + | +note: consider changing this parameter type in function `method` to borrow instead if owning the value isn't necessary + --> $DIR/custom_mut_generic.rs:11:14 + | +LL | fn method(_: impl Reborrow) {} + | ------ ^^^^^^^^^^^^^ this parameter takes ownership of the value + | | + | in this function +help: if `impl Reborrow` implemented `Clone`, you could clone the value + --> $DIR/custom_mut_generic.rs:15:24 + | +LL | fn generic_reborrow(a: impl Reborrow) { + | ^^^^^^^^^^^^^ consider constraining this type parameter with `Clone` +LL | let _ = method(a); +LL | let _ = method(a); + | - you could clone this value +help: consider restricting opaque type `impl Reborrow` with trait `Copy` + | +LL | fn generic_reborrow(a: impl Reborrow + Copy) { + | ++++++ + +error[E0382]: use of moved value: `a` + --> $DIR/custom_mut_generic.rs:20:13 + | +LL | fn generic_reborrow(a: impl Reborrow) { + | - move occurs because `a` has type `impl Reborrow`, which does not implement the `Copy` trait +... +LL | generic(a); + | - value moved here +LL | generic(a); + | ^ value used here after move + | +note: consider changing this parameter type in function `generic` to borrow instead if owning the value isn't necessary + --> $DIR/custom_mut_generic.rs:13:15 + | +LL | fn generic(_: impl Sized) {} + | ------- ^^^^^^^^^^ this parameter takes ownership of the value + | | + | in this function +help: if `impl Reborrow` implemented `Clone`, you could clone the value + --> $DIR/custom_mut_generic.rs:15:24 + | +LL | fn generic_reborrow(a: impl Reborrow) { + | ^^^^^^^^^^^^^ consider constraining this type parameter with `Clone` +... +LL | generic(a); + | - you could clone this value +help: consider restricting opaque type `impl Reborrow` with trait `Copy` + | +LL | fn generic_reborrow(a: impl Reborrow + Copy) { + | ++++++ + +error[E0382]: use of moved value: `a` + --> $DIR/custom_mut_generic.rs:22:9 + | +LL | fn generic_reborrow(a: impl Reborrow) { + | - move occurs because `a` has type `impl Reborrow`, which does not implement the `Copy` trait +... +LL | generic(a); + | - value moved here +LL | { +LL | a + | ^ value used here after move + | +note: consider changing this parameter type in function `generic` to borrow instead if owning the value isn't necessary + --> $DIR/custom_mut_generic.rs:13:15 + | +LL | fn generic(_: impl Sized) {} + | ------- ^^^^^^^^^^ this parameter takes ownership of the value + | | + | in this function +help: if `impl Reborrow` implemented `Clone`, you could clone the value + --> $DIR/custom_mut_generic.rs:15:24 + | +LL | fn generic_reborrow(a: impl Reborrow) { + | ^^^^^^^^^^^^^ consider constraining this type parameter with `Clone` +... +LL | generic(a); + | - you could clone this value +help: consider restricting opaque type `impl Reborrow` with trait `Copy` + | +LL | fn generic_reborrow(a: impl Reborrow + Copy) { + | ++++++ + +error[E0382]: use of moved value: `a` + --> $DIR/custom_mut_generic.rs:24:13 + | +LL | fn generic_reborrow(a: impl Reborrow) { + | - move occurs because `a` has type `impl Reborrow`, which does not implement the `Copy` trait +... +LL | a + | - value moved here +LL | }; +LL | generic(a); + | ^ value used here after move + | +help: if `impl Reborrow` implemented `Clone`, you could clone the value + --> $DIR/custom_mut_generic.rs:15:24 + | +LL | fn generic_reborrow(a: impl Reborrow) { + | ^^^^^^^^^^^^^ consider constraining this type parameter with `Clone` +... +LL | a + | - you could clone this value +help: consider restricting opaque type `impl Reborrow` with trait `Copy` + | +LL | fn generic_reborrow(a: impl Reborrow + Copy) { + | ++++++ + +error[E0382]: use of moved value: `a` + --> $DIR/custom_mut_generic.rs:25:18 + | +LL | fn generic_reborrow(a: impl Reborrow) { + | - move occurs because `a` has type `impl Reborrow`, which does not implement the `Copy` trait +... +LL | generic(a); + | - value moved here +LL | let _local = a; + | ^ value used here after move + | +note: consider changing this parameter type in function `generic` to borrow instead if owning the value isn't necessary + --> $DIR/custom_mut_generic.rs:13:15 + | +LL | fn generic(_: impl Sized) {} + | ------- ^^^^^^^^^^ this parameter takes ownership of the value + | | + | in this function +help: if `impl Reborrow` implemented `Clone`, you could clone the value + --> $DIR/custom_mut_generic.rs:15:24 + | +LL | fn generic_reborrow(a: impl Reborrow) { + | ^^^^^^^^^^^^^ consider constraining this type parameter with `Clone` +... +LL | generic(a); + | - you could clone this value +help: consider restricting opaque type `impl Reborrow` with trait `Copy` + | +LL | fn generic_reborrow(a: impl Reborrow + Copy) { + | ++++++ + +error[E0382]: use of moved value: `a` + --> $DIR/custom_mut_generic.rs:26:13 + | +LL | fn generic_reborrow(a: impl Reborrow) { + | - move occurs because `a` has type `impl Reborrow`, which does not implement the `Copy` trait +... +LL | let _local = a; + | - value moved here +LL | generic(a); + | ^ value used here after move + | +help: if `impl Reborrow` implemented `Clone`, you could clone the value + --> $DIR/custom_mut_generic.rs:15:24 + | +LL | fn generic_reborrow(a: impl Reborrow) { + | ^^^^^^^^^^^^^ consider constraining this type parameter with `Clone` +... +LL | let _local = a; + | - you could clone this value +help: consider restricting opaque type `impl Reborrow` with trait `Copy` + | +LL | fn generic_reborrow(a: impl Reborrow + Copy) { + | ++++++ + +error[E0382]: use of moved value: `a` + --> $DIR/custom_mut_generic.rs:27:13 + | +LL | fn generic_reborrow(a: impl Reborrow) { + | - move occurs because `a` has type `impl Reborrow`, which does not implement the `Copy` trait +... +LL | generic(a); + | - value moved here +LL | let _ = || a; + | ^^ - use occurs due to use in closure + | | + | value used here after move + | +note: consider changing this parameter type in function `generic` to borrow instead if owning the value isn't necessary + --> $DIR/custom_mut_generic.rs:13:15 + | +LL | fn generic(_: impl Sized) {} + | ------- ^^^^^^^^^^ this parameter takes ownership of the value + | | + | in this function +help: if `impl Reborrow` implemented `Clone`, you could clone the value + --> $DIR/custom_mut_generic.rs:15:24 + | +LL | fn generic_reborrow(a: impl Reborrow) { + | ^^^^^^^^^^^^^ consider constraining this type parameter with `Clone` +... +LL | generic(a); + | - you could clone this value +help: consider restricting opaque type `impl Reborrow` with trait `Copy` + | +LL | fn generic_reborrow(a: impl Reborrow + Copy) { + | ++++++ + +error[E0382]: use of moved value: `a` + --> $DIR/custom_mut_generic.rs:28:13 + | +LL | fn generic_reborrow(a: impl Reborrow) { + | - move occurs because `a` has type `impl Reborrow`, which does not implement the `Copy` trait +... +LL | let _ = || a; + | -- - variable moved due to use in closure + | | + | value moved into closure here +LL | generic(a); + | ^ value used here after move + | +help: if `impl Reborrow` implemented `Clone`, you could clone the value + --> $DIR/custom_mut_generic.rs:15:24 + | +LL | fn generic_reborrow(a: impl Reborrow) { + | ^^^^^^^^^^^^^ consider constraining this type parameter with `Clone` +... +LL | let _ = || a; + | - you could clone this value +help: consider restricting opaque type `impl Reborrow` with trait `Copy` + | +LL | fn generic_reborrow(a: impl Reborrow + Copy) { + | ++++++ + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/reborrow/reborrow-method-call.rs b/tests/ui/reborrow/reborrow-method-call.rs new file mode 100644 index 0000000000000..22a684694fed1 --- /dev/null +++ b/tests/ui/reborrow/reborrow-method-call.rs @@ -0,0 +1,28 @@ +//! Test that `impls_reborrow.method()` performs a reborrow. +//@ run-pass + +#![feature(reborrow)] + +use std::marker::{CoerceShared, PhantomData, Reborrow}; + +struct Foo<'a>(PhantomData<&'a ()>); +#[derive(Clone, Copy)] +struct FooRef<'a>(PhantomData<&'a ()>); + +impl FooRef<'_> { + fn eat_foo_ref(self) {} +} + +impl Foo<'_> { + fn eat_foo(self) {} +} + +impl<'a> Reborrow for Foo<'a> {} + +impl<'a> CoerceShared> for Foo<'a> {} + +fn main() { + let x = Foo(PhantomData); + let _reborrow = ::eat_foo(x); + let _reborrow_with_method = (x.eat_foo(), ::eat_foo_ref(x)); +} From 2fbd6315efd7898fcc6da609587c8b23ce45f38e Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Wed, 7 Oct 2026 19:11:09 -0400 Subject: [PATCH 4/5] Fix codegen tests --- library/alloc/src/vec/spec_extend.rs | 1 + .../lib-optimizations/append-elements.rs | 2 +- .../reborrow.remut.CopyProp.panic-abort.diff | 47 ------------ .../reborrow.reraw.CopyProp.panic-abort.diff | 47 ------------ tests/mir-opt/copy-prop/reborrow.rs | 24 ------- .../gvn.references.GVN.panic-abort.diff | 72 ++++++++++--------- ...slice_get.LowerIntrinsics.panic-abort.diff | 56 ++++++++------- ...ence_prop.remut.ReferencePropagation.diff} | 30 ++++---- ...ence_prop.reraw.ReferencePropagation.diff} | 30 ++++---- tests/mir-opt/reference_prop.rs | 32 +++++++-- 10 files changed, 130 insertions(+), 211 deletions(-) delete mode 100644 tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-abort.diff delete mode 100644 tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-abort.diff rename tests/mir-opt/{copy-prop/reborrow.remut.CopyProp.panic-unwind.diff => reference_prop.remut.ReferencePropagation.diff} (60%) rename tests/mir-opt/{copy-prop/reborrow.reraw.CopyProp.panic-unwind.diff => reference_prop.reraw.ReferencePropagation.diff} (60%) diff --git a/library/alloc/src/vec/spec_extend.rs b/library/alloc/src/vec/spec_extend.rs index 3f9d4504bde4c..96a1c678f961e 100644 --- a/library/alloc/src/vec/spec_extend.rs +++ b/library/alloc/src/vec/spec_extend.rs @@ -52,6 +52,7 @@ impl<'a, T: 'a, A: Allocator> SpecExtend<&'a T, slice::Iter<'a, T>> for Vec) { let slice = iterator.as_slice(); // ignore-tidy-undocumented-unsafe diff --git a/tests/codegen-llvm/lib-optimizations/append-elements.rs b/tests/codegen-llvm/lib-optimizations/append-elements.rs index 47211e3f388a0..0bf00d0460020 100644 --- a/tests/codegen-llvm/lib-optimizations/append-elements.rs +++ b/tests/codegen-llvm/lib-optimizations/append-elements.rs @@ -13,7 +13,7 @@ #[no_mangle] pub fn vec_append_with_temp_alloc(dst: &mut Vec, src: &[u8]) { // CHECK-NOT: call void @llvm.memcpy - // CHECK: call void @llvm.memcpy.{{.*}}[[DST]].i{{.*}}[[SRC]] + // CHECK: call void @llvm.memcpy.{{.*}}{{.*}}.i{{.*}}[[SRC]] // CHECK-NOT: call void @llvm.memcpy let temp = src.to_vec(); dst.extend(&temp); diff --git a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-abort.diff deleted file mode 100644 index 7ada873b82f8e..0000000000000 --- a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-abort.diff +++ /dev/null @@ -1,47 +0,0 @@ -- // MIR for `remut` before CopyProp -+ // MIR for `remut` after CopyProp - - fn remut(_1: u8) -> () { - debug x => _1; - let mut _0: (); - let _2: &mut u8; - let _5: (); - let mut _6: &mut u8; - scope 1 { - debug a => _2; - let _3: &mut u8; - scope 2 { - debug b => _3; - let _4: &mut u8; - scope 3 { -- debug c => _4; -+ debug c => _2; - } - } - } - - bb0: { - StorageLive(_2); - _2 = &mut _1; - StorageLive(_3); - _3 = &mut (*_2); -- StorageLive(_4); -- _4 = move _2; - StorageLive(_5); -- StorageLive(_6); -- _6 = move _4; -- _5 = opaque::<&mut u8>(move _6) -> [return: bb1, unwind unreachable]; -+ _5 = opaque::<&mut u8>(copy _2) -> [return: bb1, unwind unreachable]; - } - - bb1: { -- StorageDead(_6); - StorageDead(_5); - _0 = const (); -- StorageDead(_4); - StorageDead(_3); - StorageDead(_2); - return; - } - } - diff --git a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-abort.diff deleted file mode 100644 index 4fd9f5af8ee12..0000000000000 --- a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-abort.diff +++ /dev/null @@ -1,47 +0,0 @@ -- // MIR for `reraw` before CopyProp -+ // MIR for `reraw` after CopyProp - - fn reraw(_1: u8) -> () { - debug x => _1; - let mut _0: (); - let _2: &mut u8; - let _5: (); - let mut _6: &mut u8; - scope 1 { - debug a => _2; - let _3: *mut u8; - scope 2 { - debug b => _3; - let _4: &mut u8; - scope 3 { -- debug c => _4; -+ debug c => _2; - } - } - } - - bb0: { - StorageLive(_2); - _2 = &mut _1; - StorageLive(_3); - _3 = &raw mut (*_2); -- StorageLive(_4); -- _4 = move _2; - StorageLive(_5); -- StorageLive(_6); -- _6 = move _4; -- _5 = opaque::<&mut u8>(move _6) -> [return: bb1, unwind unreachable]; -+ _5 = opaque::<&mut u8>(copy _2) -> [return: bb1, unwind unreachable]; - } - - bb1: { -- StorageDead(_6); - StorageDead(_5); - _0 = const (); -- StorageDead(_4); - StorageDead(_3); - StorageDead(_2); - return; - } - } - diff --git a/tests/mir-opt/copy-prop/reborrow.rs b/tests/mir-opt/copy-prop/reborrow.rs index 8bc81106e9945..1d257d91acd1d 100644 --- a/tests/mir-opt/copy-prop/reborrow.rs +++ b/tests/mir-opt/copy-prop/reborrow.rs @@ -5,28 +5,6 @@ #[inline(never)] fn opaque(_: impl Sized) {} -// EMIT_MIR reborrow.remut.CopyProp.diff -fn remut(mut x: u8) { - // CHECK-LABEL: fn remut( - // CHECK: debug a => [[a:_.*]]; - // CHECK: debug c => [[a]]; - let a = &mut x; - let b = &mut *a; //< this cannot mutate a. - let c = a; //< so `c` and `a` can be merged. - opaque(c); -} - -// EMIT_MIR reborrow.reraw.CopyProp.diff -fn reraw(mut x: u8) { - // CHECK-LABEL: fn reraw( - // CHECK: debug a => [[a:_.*]]; - // CHECK: debug c => [[a]]; - let a = &mut x; - let b = &raw mut *a; //< this cannot mutate a. - let c = a; //< so `c` and `a` can be merged. - opaque(c); -} - // EMIT_MIR reborrow.miraw.CopyProp.diff fn miraw(mut x: u8) { // CHECK-LABEL: fn miraw( @@ -50,8 +28,6 @@ fn demiraw(mut x: u8) { } fn main() { - remut(0); - reraw(0); miraw(0); demiraw(0); } diff --git a/tests/mir-opt/gvn.references.GVN.panic-abort.diff b/tests/mir-opt/gvn.references.GVN.panic-abort.diff index 429c7df2f361e..5aa57f61c0e51 100644 --- a/tests/mir-opt/gvn.references.GVN.panic-abort.diff +++ b/tests/mir-opt/gvn.references.GVN.panic-abort.diff @@ -23,14 +23,17 @@ let _18: &mut impl Sized; let mut _20: S<&mut impl Sized>; let mut _21: &mut impl Sized; - let _22: (); - let mut _23: &impl Sized; + let mut _22: &mut impl Sized; + let mut _23: &mut impl Sized; let _24: (); - let mut _25: &mut impl Sized; + let mut _25: &impl Sized; let _26: (); - let mut _27: *const impl Sized; + let mut _27: &mut impl Sized; let _28: (); - let mut _29: *mut impl Sized; + let mut _29: *const impl Sized; + let _30: (); + let mut _31: *mut impl Sized; + let mut _32: &mut impl Sized; scope 1 { debug r => _18; let _19: &mut impl Sized; @@ -117,54 +120,59 @@ StorageLive(_19); StorageLive(_20); StorageLive(_21); -- _21 = move _18; + _22 = &mut (*_18); +- _21 = move _22; - _20 = S::<&mut impl Sized>(move _21); -+ _21 = copy _18; -+ _20 = S::<&mut impl Sized>(copy _18); ++ _21 = copy _22; ++ _20 = S::<&mut impl Sized>(copy _22); StorageDead(_21); -- _19 = move (_20.0: &mut impl Sized); -+ _19 = copy _18; +- _32 = no_retag copy (_20.0: &mut impl Sized); +- _23 = &mut (*_32); +- _19 = move _23; ++ _32 = no_retag copy _22; ++ _23 = &mut (*_22); ++ _19 = copy _23; StorageDead(_20); - StorageLive(_22); - StorageLive(_23); -- _23 = &(*_19); -+ _23 = &(*_18); - _22 = opaque::<&impl Sized>(move _23) -> [return: bb9, unwind unreachable]; - } - - bb9: { - StorageDead(_23); - StorageDead(_22); StorageLive(_24); StorageLive(_25); -- _25 = &mut (*_19); -+ _25 = &mut (*_18); - _24 = opaque::<&mut impl Sized>(move _25) -> [return: bb10, unwind unreachable]; +- _25 = &(*_19); ++ _25 = &(*_23); + _24 = opaque::<&impl Sized>(move _25) -> [return: bb9, unwind unreachable]; } - bb10: { + bb9: { StorageDead(_25); StorageDead(_24); StorageLive(_26); StorageLive(_27); -- _27 = &raw const (*_19); -+ _27 = &raw const (*_18); - _26 = opaque::<*const impl Sized>(move _27) -> [return: bb11, unwind unreachable]; +- _27 = &mut (*_19); ++ _27 = &mut (*_23); + _26 = opaque::<&mut impl Sized>(move _27) -> [return: bb10, unwind unreachable]; } - bb11: { + bb10: { StorageDead(_27); StorageDead(_26); StorageLive(_28); StorageLive(_29); -- _29 = &raw mut (*_19); -+ _29 = &raw mut (*_18); - _28 = opaque::<*mut impl Sized>(move _29) -> [return: bb12, unwind unreachable]; +- _29 = &raw const (*_19); ++ _29 = &raw const (*_23); + _28 = opaque::<*const impl Sized>(move _29) -> [return: bb11, unwind unreachable]; } - bb12: { + bb11: { StorageDead(_29); StorageDead(_28); + StorageLive(_30); + StorageLive(_31); +- _31 = &raw mut (*_19); ++ _31 = &raw mut (*_23); + _30 = opaque::<*mut impl Sized>(move _31) -> [return: bb12, unwind unreachable]; + } + + bb12: { + StorageDead(_31); + StorageDead(_30); _0 = const (); StorageDead(_19); StorageDead(_18); diff --git a/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-abort.diff index d18bdc431683f..787a31367db8d 100644 --- a/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-abort.diff +++ b/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-abort.diff @@ -13,13 +13,14 @@ let mut _8: usize; let mut _9: &mut i16; let mut _10: &mut [i16]; - let mut _11: usize; - let mut _12: *const i32; - let mut _13: *const [i32]; - let mut _14: usize; - let mut _15: *mut i64; - let mut _16: *mut [i64]; - let mut _17: usize; + let mut _11: &mut [i16]; + let mut _12: usize; + let mut _13: *const i32; + let mut _14: *const [i32]; + let mut _15: usize; + let mut _16: *mut i64; + let mut _17: *mut [i64]; + let mut _18: usize; bb0: { StorageLive(_6); @@ -37,46 +38,47 @@ StorageDead(_7); StorageLive(_9); StorageLive(_10); - _10 = move _2; - StorageLive(_11); - _11 = copy _5; -- _9 = slice_get_unchecked::<&mut i16, &mut [i16], i16>(move _10, move _11) -> [return: bb2, unwind unreachable]; -+ _9 = &mut (*_10)[_11]; + _11 = &mut (*_2); + _10 = move _11; + StorageLive(_12); + _12 = copy _5; +- _9 = slice_get_unchecked::<&mut i16, &mut [i16], i16>(move _10, move _12) -> [return: bb2, unwind unreachable]; ++ _9 = &mut (*_10)[_12]; + goto -> bb2; } bb2: { - StorageDead(_11); + StorageDead(_12); StorageDead(_10); - StorageLive(_12); StorageLive(_13); - _13 = copy _3; StorageLive(_14); - _14 = copy _5; -- _12 = slice_get_unchecked::<*const i32, *const [i32], i32>(move _13, move _14) -> [return: bb3, unwind unreachable]; -+ _12 = &raw const (*_13)[_14]; + _14 = copy _3; + StorageLive(_15); + _15 = copy _5; +- _13 = slice_get_unchecked::<*const i32, *const [i32], i32>(move _14, move _15) -> [return: bb3, unwind unreachable]; ++ _13 = &raw const (*_14)[_15]; + goto -> bb3; } bb3: { + StorageDead(_15); StorageDead(_14); - StorageDead(_13); - StorageLive(_15); StorageLive(_16); - _16 = copy _4; StorageLive(_17); - _17 = copy _5; -- _15 = slice_get_unchecked::<*mut i64, *mut [i64], i64>(move _16, move _17) -> [return: bb4, unwind unreachable]; -+ _15 = &raw mut (*_16)[_17]; + _17 = copy _4; + StorageLive(_18); + _18 = copy _5; +- _16 = slice_get_unchecked::<*mut i64, *mut [i64], i64>(move _17, move _18) -> [return: bb4, unwind unreachable]; ++ _16 = &raw mut (*_17)[_18]; + goto -> bb4; } bb4: { + StorageDead(_18); StorageDead(_17); + _0 = (move _6, move _9, move _13, move _16); StorageDead(_16); - _0 = (move _6, move _9, move _12, move _15); - StorageDead(_15); - StorageDead(_12); + StorageDead(_13); StorageDead(_9); StorageDead(_6); return; diff --git a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-unwind.diff b/tests/mir-opt/reference_prop.remut.ReferencePropagation.diff similarity index 60% rename from tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-unwind.diff rename to tests/mir-opt/reference_prop.remut.ReferencePropagation.diff index 9df4ba62b566f..ce574b1a8818f 100644 --- a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/reference_prop.remut.ReferencePropagation.diff @@ -1,5 +1,5 @@ -- // MIR for `remut` before CopyProp -+ // MIR for `remut` after CopyProp +- // MIR for `remut` before ReferencePropagation ++ // MIR for `remut` after ReferencePropagation fn remut(_1: u8) -> () { debug x => _1; @@ -13,39 +13,41 @@ debug a => _2; let _3: &mut u8; scope 2 { - debug b => _3; +- debug b => _3; ++ debug b => _2; let _4: &mut u8; scope 3 { - debug c => _4; -+ debug c => _5; ++ debug c => _2; } } } bb0: { - StorageLive(_2); +- StorageLive(_2); _2 = &mut _1; - StorageLive(_3); - _3 = &mut (*_2); +- StorageLive(_3); +- _3 = &mut (*_2); - StorageLive(_4); - _5 = &mut (*_2); +- _5 = &mut (*_2); - _4 = move _5; StorageLive(_6); -- StorageLive(_7); + StorageLive(_7); - _8 = &mut (*_4); - _7 = move _8; - _6 = opaque::<&mut u8>(move _7) -> [return: bb1, unwind continue]; -+ _8 = &mut (*_5); -+ _6 = opaque::<&mut u8>(copy _8) -> [return: bb1, unwind continue]; ++ _8 = &mut _1; ++ _7 = copy _8; ++ _6 = opaque::<&mut u8>(copy _7) -> [return: bb1, unwind continue]; } bb1: { -- StorageDead(_7); + StorageDead(_7); StorageDead(_6); _0 = const (); - StorageDead(_4); - StorageDead(_3); - StorageDead(_2); +- StorageDead(_3); +- StorageDead(_2); return; } } diff --git a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-unwind.diff b/tests/mir-opt/reference_prop.reraw.ReferencePropagation.diff similarity index 60% rename from tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-unwind.diff rename to tests/mir-opt/reference_prop.reraw.ReferencePropagation.diff index d73c15f8a9fed..e5e538b5fcc07 100644 --- a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.panic-unwind.diff +++ b/tests/mir-opt/reference_prop.reraw.ReferencePropagation.diff @@ -1,5 +1,5 @@ -- // MIR for `reraw` before CopyProp -+ // MIR for `reraw` after CopyProp +- // MIR for `reraw` before ReferencePropagation ++ // MIR for `reraw` after ReferencePropagation fn reraw(_1: u8) -> () { debug x => _1; @@ -13,39 +13,41 @@ debug a => _2; let _3: *mut u8; scope 2 { - debug b => _3; +- debug b => _3; ++ debug b => _2; let _4: &mut u8; scope 3 { - debug c => _4; -+ debug c => _5; ++ debug c => _2; } } } bb0: { - StorageLive(_2); +- StorageLive(_2); _2 = &mut _1; - StorageLive(_3); - _3 = &raw mut (*_2); +- StorageLive(_3); +- _3 = &raw mut (*_2); - StorageLive(_4); - _5 = &mut (*_2); +- _5 = &mut (*_2); - _4 = move _5; StorageLive(_6); -- StorageLive(_7); + StorageLive(_7); - _8 = &mut (*_4); - _7 = move _8; - _6 = opaque::<&mut u8>(move _7) -> [return: bb1, unwind continue]; -+ _8 = &mut (*_5); -+ _6 = opaque::<&mut u8>(copy _8) -> [return: bb1, unwind continue]; ++ _8 = &mut _1; ++ _7 = copy _8; ++ _6 = opaque::<&mut u8>(copy _7) -> [return: bb1, unwind continue]; } bb1: { -- StorageDead(_7); + StorageDead(_7); StorageDead(_6); _0 = const (); - StorageDead(_4); - StorageDead(_3); - StorageDead(_2); +- StorageDead(_3); +- StorageDead(_2); return; } } diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs index c4b63b6313c23..bc8cdbdbb5036 100644 --- a/tests/mir-opt/reference_prop.rs +++ b/tests/mir-opt/reference_prop.rs @@ -233,7 +233,7 @@ fn reference_propagation_mut<'a, T: Copy>(single: &'a mut T, mut multiple: &'a m // CHECK: bb4: { // CHECK: [[a:_.*]] = const 7_usize; // CHECK: [[b:_.*]] = &mut [[a]]; - // CHECK: [[c:_.*]] = copy (*[[b]]); + // CHECK: [[c:_.*]] = copy [[a]]; let mut a = 7_usize; let b = &mut a; @@ -246,10 +246,8 @@ fn reference_propagation_mut<'a, T: Copy>(single: &'a mut T, mut multiple: &'a m // CHECK: bb5: { // CHECK: [[a:_.*]] = const 7_usize; // CHECK: [[b1:_.*]] = &mut [[a]]; - // CHECK: [[c:_.*]] = copy (*[[b1]]); - // CHECK: [[b2:_.*]] = copy [[b1]]; - // CHECK: [[c2:_.*]] = copy (*[[b2]]); - // CHECK: [[b3:_.*]] = copy [[b2]]; + // CHECK: [[c:_.*]] = copy [[a]]; + // CHECK: [[c2:_.*]] = copy [[a]]; let mut a = 7_usize; let b1 = &mut a; @@ -864,6 +862,26 @@ fn many_debuginfo() { &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&a; } +fn remut(mut x: u8) { + // CHECK-LABEL: fn remut( + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug c => [[a]]; + let a = &mut x; + let b = &mut *a; //< this cannot mutate a. + let c = a; //< so `c` and `a` can be merged. + opaque(c); +} + +fn reraw(mut x: u8) { + // CHECK-LABEL: fn reraw( + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug c => [[a]]; + let a = &mut x; + let b = &raw mut *a; //< this cannot mutate a. + let c = a; //< so `c` and `a` can be merged. + opaque(c); +} + fn main() { let mut x = 5_usize; let mut y = 7_usize; @@ -879,6 +897,8 @@ fn main() { unique_with_copies(); debuginfo(); many_debuginfo(); + remut(42); + reraw(42); } // EMIT_MIR reference_prop.reference_propagation.ReferencePropagation.diff @@ -892,3 +912,5 @@ fn main() { // EMIT_MIR reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff // EMIT_MIR reference_prop.unique_with_copies.ReferencePropagation.diff // EMIT_MIR reference_prop.debuginfo.ReferencePropagation.diff +// EMIT_MIR reference_prop.remut.ReferencePropagation.diff +// EMIT_MIR reference_prop.reraw.ReferencePropagation.diff From 937c10e8277d2b255c5381d0e57cea4a2261ff89 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Thu, 8 Oct 2026 11:24:22 -0400 Subject: [PATCH 5/5] Don't make THIR exprs for generic mutable reborrows We don't need these anymore, now that the reborrows get inserted in MIR. We keep them around in HIR for closure capture inference. --- compiler/rustc_middle/src/mir/syntax.rs | 5 +++-- compiler/rustc_middle/src/thir.rs | 5 ++--- compiler/rustc_middle/src/thir/visit.rs | 4 +--- compiler/rustc_middle/src/ty/adjustment.rs | 5 +++-- compiler/rustc_mir_build/src/builder/expr/as_place.rs | 2 +- compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs | 6 +++--- compiler/rustc_mir_build/src/builder/expr/category.rs | 2 +- compiler/rustc_mir_build/src/builder/expr/into.rs | 4 ++-- compiler/rustc_mir_build/src/check_unsafety.rs | 2 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 7 ++++--- compiler/rustc_mir_build/src/thir/pattern/check_match.rs | 2 +- compiler/rustc_mir_build/src/thir/print.rs | 5 ++--- compiler/rustc_ty_utils/src/consts.rs | 4 ++-- 13 files changed, 26 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 6bb0190cd70b8..36746bbccd4a9 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1481,9 +1481,10 @@ pub enum Rvalue<'tcx> { /// Future work may add support for multiple lifetimes and changing memory layout as part of /// CoerceShared. These may be end up implemented as multiple MIR operations. /// - /// This is produced by the [`ExprKind::Reborrow`]. + /// This is produced by [`ExprKind::CoerceShared`], + /// and by `consume_by_copy_reborrow_or_move()` in `rustc_mir_build`. /// - /// [`ExprKind::Reborrow`]: crate::thir::ExprKind::Reborrow + /// [`ExprKind::CoerceShared`]: crate::thir::ExprKind::CoerceShared Reborrow(Ty<'tcx>, Mutability, Place<'tcx>), } diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index a3e5168e4f1e9..9d5c030f2a371 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -554,16 +554,15 @@ pub enum ExprKind<'tcx> { Yield { value: ExprId, }, - /// Use of an ADT that implements the Reborrow (for Mut) or CoerceShared traits (for Not). This + /// Use of an ADT that implements the CoerceShared trait. This /// expression is produced by the [`Adjust::GenericReborrow`] in places where normally the ADT /// would be moved or assigned over. Instead, this produces an [`Rvalue::Reborrow`] which /// produces a bitwise copy of the source ADT and disables the source for the copy's lifetime. /// /// [`Adjust::GenericReborrow`]: crate::ty::adjustment::Adjust::GenericReborrow /// [`Rvalue::Reborrow`]: mir::Rvalue::Reborrow - Reborrow { + CoerceShared { source: ExprId, - mutability: Mutability, target: Ty<'tcx>, }, } diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index c76e993f92f7d..2a9569cc768a3 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -187,9 +187,7 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( } ThreadLocalRef(_) => {} Yield { value } => visitor.visit_expr(&visitor.thir()[value]), - Reborrow { source, mutability: _, target: _ } => { - visitor.visit_expr(&visitor.thir()[source]) - } + CoerceShared { source, target: _ } => visitor.visit_expr(&visitor.thir()[source]), } } diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index b3a2925b24bfa..4fbed592ee73b 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -107,9 +107,10 @@ pub enum Adjust { /// Take a user-type T implementing the Reborrow trait (for Mut) or the CoerceShared trait (for /// Not) and reborrow as `T` or `CoreceShared`. /// - /// This produces an [`ExprKind::Reborrow`]. + /// Thu Not form produces an [`ExprKind::CoerceShared`]; the Mut one produces no THIR, + /// and exists only for closure capture inference. /// - /// [`ExprKind::Reborrow`]: crate::thir::ExprKind::Reborrow + /// [`ExprKind::CoerceShared`]: crate::thir::ExprKind::CoerceShared GenericReborrow(hir::Mutability), } diff --git a/compiler/rustc_mir_build/src/builder/expr/as_place.rs b/compiler/rustc_mir_build/src/builder/expr/as_place.rs index d3b32e25fa98b..5bc2b41149e6c 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_place.rs @@ -587,7 +587,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // A reborrow is an rvalue. If a place is needed for it, materialize // the rvalue in a temporary instead of treating the reborrow // expression itself as an assignable place. - | ExprKind::Reborrow { .. } + | ExprKind::CoerceShared { .. } | ExprKind::WrapUnsafeBinder { .. } => { // these are not places, so we need to make a temporary. debug_assert!(!matches!(Category::of(&expr.kind), Some(Category::Place))); diff --git a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs index b36a6ce6952ac..518492a18d726 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs @@ -435,9 +435,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); block.and(Rvalue::Use(operand, WithRetag::Yes)) } - ExprKind::Reborrow { source, mutability, target } => { - let temp = unpack!(block = this.as_temp(block, scope, source, mutability)); - block.and(Rvalue::Reborrow(target, mutability, temp.into())) + ExprKind::CoerceShared { source, target } => { + let temp = unpack!(block = this.as_temp(block, scope, source, Mutability::Not)); + block.and(Rvalue::Reborrow(target, Mutability::Not, temp.into())) } } } diff --git a/compiler/rustc_mir_build/src/builder/expr/category.rs b/compiler/rustc_mir_build/src/builder/expr/category.rs index 9e5e4c16d9d96..cfd8a16888583 100644 --- a/compiler/rustc_mir_build/src/builder/expr/category.rs +++ b/compiler/rustc_mir_build/src/builder/expr/category.rs @@ -72,7 +72,7 @@ impl Category { // A reborrow expression produces a value represented in MIR as // `Rvalue::Reborrow`. Its source may be a place, but the reborrow // expression itself does not denote an assignable place. - | ExprKind::Reborrow { .. } + | ExprKind::CoerceShared { .. } | ExprKind::ThreadLocalRef(_) | ExprKind::WrapUnsafeBinder { .. } => Some(Category::Rvalue(RvalueFunc::AsRvalue)), diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index 2da77b3079e8a..5fbdb8cf05028 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -921,13 +921,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.cfg.push_assign(block, source_info, destination, rvalue); block.unit() } - ExprKind::Reborrow { source, mutability, target } => { + ExprKind::CoerceShared { source, target } => { let place = unpack!(block = this.as_place(block, source)); this.cfg.push_assign( block, source_info, destination, - Rvalue::Reborrow(target, mutability, place), + Rvalue::Reborrow(target, Mutability::Not, place), ); block.unit() } diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index e83c3560a1ee9..7cf9dc1326f99 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -394,7 +394,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { | ExprKind::InlineAsm { .. } | ExprKind::LogicalOp { .. } | ExprKind::ValueExpr { .. } - | ExprKind::Reborrow { .. } => { + | ExprKind::CoerceShared { .. } => { // We don't need to save the old value and restore it // because all the place expressions can't have more // than one child. diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 16e92ae2c51e4..9d6c4db990b56 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -289,13 +289,14 @@ impl<'tcx> ThirBuildCx<'tcx> { debug!(?kind); kind } - Adjust::GenericReborrow(mutability) => { + Adjust::GenericReborrow(ty::Mutability::Not) => { let expr = self.thir.exprs.push(expr); - let kind = - ExprKind::Reborrow { source: expr, mutability, target: adjustment.target }; + let kind = ExprKind::CoerceShared { source: expr, target: adjustment.target }; kind } + // These get inserted in MIR building `consume_by_copy_reborrow_or_move` + Adjust::GenericReborrow(ty::Mutability::Mut) => return expr, }; Expr { temp_scope_id, ty: adjustment.target, span, kind } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index b434bd17e2d8e..14c35fb11ec6e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -359,7 +359,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { | VarRef { .. } | ZstLiteral { .. } | Yield { .. } - | Reborrow { .. } => true, + | CoerceShared { .. } => true, } } diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 7cfd313218d33..6c125347bcd2a 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -601,10 +601,9 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { self.print_expr(*value, depth_lvl + 2); print_indented!(self, "}", depth_lvl); } - ExprKind::Reborrow { source: _, mutability: _, target: _ } => { - print_indented!(self, "Reborrow {", depth_lvl); + CoerceShared { source: _, target: _ } => { + print_indented!(self, "CoerceShared {", depth_lvl); print_indented!(self, "source:", depth_lvl + 1); - print_indented!(self, "mutability:", depth_lvl + 1); print_indented!(self, "ty:", depth_lvl + 1); print_indented!(self, "}", depth_lvl); } diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 79369e5715d21..a2a225d69b76c 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -222,7 +222,7 @@ fn recurse_build<'tcx>( | ExprKind::ThreadLocalRef(_) => { error(GenericConstantTooComplexSub::OperationNotSupported(node.span))? } - ExprKind::Reborrow { .. } => { + ExprKind::CoerceShared { .. } => { unimplemented!(); } }) @@ -322,7 +322,7 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> { | thir::ExprKind::InlineAsm(_) | thir::ExprKind::ThreadLocalRef(_) | thir::ExprKind::Yield { .. } => false, - thir::ExprKind::Reborrow { .. } => { + thir::ExprKind::CoerceShared { .. } => { unimplemented!(); } }