From 7e226e6d3f5dc5c39a222091f7a234c1480e1cbd Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 5 Sep 2022 05:00:26 +0000 Subject: [PATCH] Look at move place's type when suggesting mutable reborrow --- .../src/diagnostics/conflict_errors.rs | 1 - .../rustc_borrowck/src/diagnostics/mod.rs | 9 ++++--- .../src/diagnostics/move_errors.rs | 2 +- .../reborrow-sugg-move-then-borrow.rs | 26 +++++++++++++++++++ .../reborrow-sugg-move-then-borrow.stderr | 24 +++++++++++++++++ 5 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/borrowck/reborrow-sugg-move-then-borrow.rs create mode 100644 src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 5971f7623f215..a2e4641f66d5c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -198,7 +198,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { move_span, move_spans, *moved_place, - Some(used_place), partially_str, loop_message, move_msg, diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 683084cf09d44..2d849316f9294 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -970,7 +970,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { move_span: Span, move_spans: UseSpans<'tcx>, moved_place: Place<'tcx>, - used_place: Option>, partially_str: &str, loop_message: &str, move_msg: &str, @@ -1058,9 +1057,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { place_name, partially_str, loop_message ), ); - // If we have a `&mut` ref, we need to reborrow. - if let Some(ty::Ref(_, _, hir::Mutability::Mut)) = used_place - .map(|used_place| used_place.ty(self.body, self.infcx.tcx).ty.kind()) + // 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() { // If we are in a loop this will be suggested later. if !is_loop_move { diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 16c2f9ccc6aa4..bb06a94635c46 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -401,7 +401,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; if let Some(use_spans) = use_spans { self.explain_captures( - &mut err, span, span, use_spans, move_place, None, "", "", "", false, true, + &mut err, span, span, use_spans, move_place, "", "", "", false, true, ); } err diff --git a/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.rs b/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.rs new file mode 100644 index 0000000000000..31eba07400846 --- /dev/null +++ b/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.rs @@ -0,0 +1,26 @@ +// Tests the suggestion to reborrow the first move site +// when we move then borrow a `&mut` ref. + +struct State; + +impl IntoIterator for &mut State { + type IntoIter = std::vec::IntoIter<()>; + type Item = (); + + fn into_iter(self) -> Self::IntoIter { + vec![].into_iter() + } +} + +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 main() {} diff --git a/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr b/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr new file mode 100644 index 0000000000000..13a2005e2ef4c --- /dev/null +++ b/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr @@ -0,0 +1,24 @@ +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: this function takes ownership of the receiver `self`, which moves `state` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + | +LL | fn into_iter(self) -> Self::IntoIter; + | ^^^^ +help: consider creating a fresh reborrow of `state` here + | +LL | for _ in &mut *state {} + | ++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`.