Skip to content

Commit d7d42cc

Browse files
authored
Rollup merge of #83945 - SkiFire13:fix-83924, r=estebank
Add suggestion to reborrow mutable references when they're moved in a for loop Address #83924
2 parents 9c688cd + a775984 commit d7d42cc

File tree

4 files changed

+83
-1
lines changed

4 files changed

+83
-1
lines changed

compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
264264

265265
if let Some(DesugaringKind::ForLoop(_)) = move_span.desugaring_kind() {
266266
let sess = self.infcx.tcx.sess;
267-
if let Ok(snippet) = sess.source_map().span_to_snippet(move_span) {
267+
let ty = used_place.ty(self.body, self.infcx.tcx).ty;
268+
// If we have a `&mut` ref, we need to reborrow.
269+
if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() {
270+
// If we are in a loop this will be suggested later.
271+
if !is_loop_move {
272+
err.span_suggestion_verbose(
273+
move_span.shrink_to_lo(),
274+
&format!(
275+
"consider creating a fresh reborrow of {} here",
276+
self.describe_place(moved_place.as_ref())
277+
.map(|n| format!("`{}`", n))
278+
.unwrap_or_else(|| "the mutable reference".to_string()),
279+
),
280+
format!("&mut *"),
281+
Applicability::MachineApplicable,
282+
);
283+
}
284+
} else if let Ok(snippet) = sess.source_map().span_to_snippet(move_span) {
268285
err.span_suggestion(
269286
move_span,
270287
"consider borrowing to avoid moving into the for loop",

src/test/ui/issues/issue-83924.fixed

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// run-rustfix
2+
3+
fn main() {
4+
let mut values = vec![10, 11, 12];
5+
let v = &mut values;
6+
7+
let mut max = 0;
8+
9+
for n in &mut *v {
10+
max = std::cmp::max(max, *n);
11+
}
12+
13+
println!("max is {}", max);
14+
println!("Converting to percentages of maximum value...");
15+
for n in v {
16+
//~^ ERROR: use of moved value: `v` [E0382]
17+
*n = 100 * (*n) / max;
18+
}
19+
println!("values: {:#?}", values);
20+
}

src/test/ui/issues/issue-83924.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// run-rustfix
2+
3+
fn main() {
4+
let mut values = vec![10, 11, 12];
5+
let v = &mut values;
6+
7+
let mut max = 0;
8+
9+
for n in v {
10+
max = std::cmp::max(max, *n);
11+
}
12+
13+
println!("max is {}", max);
14+
println!("Converting to percentages of maximum value...");
15+
for n in v {
16+
//~^ ERROR: use of moved value: `v` [E0382]
17+
*n = 100 * (*n) / max;
18+
}
19+
println!("values: {:#?}", values);
20+
}

src/test/ui/issues/issue-83924.stderr

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0382]: use of moved value: `v`
2+
--> $DIR/issue-83924.rs:15:14
3+
|
4+
LL | let v = &mut values;
5+
| - move occurs because `v` has type `&mut Vec<i32>`, which does not implement the `Copy` trait
6+
...
7+
LL | for n in v {
8+
| - `v` moved due to this implicit call to `.into_iter()`
9+
...
10+
LL | for n in v {
11+
| ^ value used here after move
12+
|
13+
note: this function takes ownership of the receiver `self`, which moves `v`
14+
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
15+
|
16+
LL | fn into_iter(self) -> Self::IntoIter;
17+
| ^^^^
18+
help: consider creating a fresh reborrow of `v` here
19+
|
20+
LL | for n in &mut *v {
21+
| ^^^^^^
22+
23+
error: aborting due to previous error
24+
25+
For more information about this error, try `rustc --explain E0382`.

0 commit comments

Comments
 (0)