Look at move place's type when suggesting mutable reborrow
This commit is contained in:
parent
a2cdcb3fea
commit
7e226e6d3f
@ -198,7 +198,6 @@ pub(crate) fn report_use_of_moved_or_uninitialized(
|
||||
move_span,
|
||||
move_spans,
|
||||
*moved_place,
|
||||
Some(used_place),
|
||||
partially_str,
|
||||
loop_message,
|
||||
move_msg,
|
||||
|
@ -970,7 +970,6 @@ fn explain_captures(
|
||||
move_span: Span,
|
||||
move_spans: UseSpans<'tcx>,
|
||||
moved_place: Place<'tcx>,
|
||||
used_place: Option<PlaceRef<'tcx>>,
|
||||
partially_str: &str,
|
||||
loop_message: &str,
|
||||
move_msg: &str,
|
||||
@ -1058,9 +1057,11 @@ fn explain_captures(
|
||||
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 {
|
||||
|
@ -401,7 +401,7 @@ fn report_cannot_move_from_borrowed_content(
|
||||
};
|
||||
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
|
||||
|
26
src/test/ui/borrowck/reborrow-sugg-move-then-borrow.rs
Normal file
26
src/test/ui/borrowck/reborrow-sugg-move-then-borrow.rs
Normal file
@ -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() {}
|
24
src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr
Normal file
24
src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr
Normal file
@ -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`.
|
Loading…
Reference in New Issue
Block a user