From 4362da13b128e897712140b3c11397e871e5b2fc Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 12 Jan 2021 17:31:13 +0900 Subject: [PATCH] Do not suggest invalid code in pattern with loop --- .../borrow_check/diagnostics/conflict_errors.rs | 5 ++++- .../ui/borrowck/move-in-pattern-mut-in-loop.rs | 10 ++++++++++ .../borrowck/move-in-pattern-mut-in-loop.stderr | 15 +++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/borrowck/move-in-pattern-mut-in-loop.rs create mode 100644 src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs index db02ee67910b2..c745601c33678 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs @@ -141,6 +141,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.add_moved_or_invoked_closure_note(location, used_place, &mut err); let mut is_loop_move = false; + let mut in_pattern = false; for move_site in &move_site_vec { let move_out = self.move_data.moves[(*move_site).moi]; @@ -256,6 +257,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "ref ".to_string(), Applicability::MachineApplicable, ); + in_pattern = true; } if let Some(DesugaringKind::ForLoop(_)) = move_span.desugaring_kind() { @@ -302,7 +304,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let place = &self.move_data.move_paths[mpi].place; let ty = place.ty(self.body, self.infcx.tcx).ty; - if is_loop_move { + // If we're in pattern, we do nothing in favor of the previous suggestion (#80913). + if is_loop_move & !in_pattern { if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() { // We have a `&mut` ref, we need to reborrow on each iteration (#62112). err.span_suggestion_verbose( diff --git a/src/test/ui/borrowck/move-in-pattern-mut-in-loop.rs b/src/test/ui/borrowck/move-in-pattern-mut-in-loop.rs new file mode 100644 index 0000000000000..4b42f9d4cd580 --- /dev/null +++ b/src/test/ui/borrowck/move-in-pattern-mut-in-loop.rs @@ -0,0 +1,10 @@ +// Regression test for #80913. + +fn main() { + let mut x = 42_i32; + let mut opt = Some(&mut x); + for _ in 0..5 { + if let Some(mut _x) = opt {} + //~^ ERROR: use of moved value + } +} diff --git a/src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr b/src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr new file mode 100644 index 0000000000000..9373e4d95fccd --- /dev/null +++ b/src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr @@ -0,0 +1,15 @@ +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 field in the pattern to avoid moving `opt.0` + | +LL | if let Some(ref mut _x) = opt {} + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`.