Skip to content

Commit 4b195d1

Browse files
Rollup merge of rust-lang#149863 - estebank:issue-149861, r=mati865
Do not suggest moving expression out of for loop when hitting `break` from desugaring Fix rust-lang#149861.
2 parents b037c15 + c60ed21 commit 4b195d1

File tree

6 files changed

+74
-40
lines changed

6 files changed

+74
-40
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4521,7 +4521,9 @@ struct BreakFinder {
45214521
impl<'hir> Visitor<'hir> for BreakFinder {
45224522
fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
45234523
match ex.kind {
4524-
hir::ExprKind::Break(destination, _) => {
4524+
hir::ExprKind::Break(destination, _)
4525+
if !ex.span.is_desugaring(DesugaringKind::ForLoop) =>
4526+
{
45254527
self.found_breaks.push((destination, ex.span));
45264528
}
45274529
hir::ExprKind::Continue(destination) => {

tests/ui/ergonomic-clones/closure/spawn-thread.edition2018.stderr

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,6 @@ LL | | drop((x.0, x.1, x.2));
1212
| | --- use occurs due to use in closure
1313
LL | | });
1414
| |_________- value moved here, in previous iteration of loop
15-
|
16-
help: consider moving the expression out of the loop so it is only moved once
17-
|
18-
LL ~ let mut value = std::thread::spawn(use || {
19-
LL +
20-
LL + drop((x.0, x.1, x.2));
21-
LL + });
22-
LL ~ for _ in 0..10 {
23-
LL ~ let handler = value;
24-
|
2515

2616
error: aborting due to 1 previous error
2717

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
use std::thread;
2+
use std::sync::{Arc, Mutex, Condvar};
3+
use std::collections::VecDeque;
4+
5+
type Job = Box<dyn FnOnce() + Send + 'static>;
6+
7+
struct ThreadPool {
8+
workers: Vec<thread::JoinHandle<()>>,
9+
queue: Arc<()>,
10+
}
11+
12+
impl ThreadPool {
13+
fn execute<F>(&self, f: F)
14+
where
15+
F: FnOnce() + Send + 'static,
16+
{
17+
panic!()
18+
}
19+
}
20+
21+
fn main() {
22+
let results = Arc::new(Mutex::new(Vec::new())); //~ NOTE move occurs because
23+
let pool = ThreadPool {
24+
workers: vec![],
25+
queue: Arc::new(()),
26+
};
27+
28+
for i in 0..20 { //~ NOTE inside of this loop
29+
// let results = Arc::clone(&results); // Forgot this.
30+
pool.execute(move || { //~ ERROR E0382
31+
//~^ NOTE value moved into closure here, in previous iteration of loop
32+
//~| HELP consider cloning the value before moving it into the closure
33+
let mut r = results.lock().unwrap(); //~ NOTE use occurs due to use in closure
34+
r.push(i);
35+
});
36+
}
37+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0382]: use of moved value: `results`
2+
--> $DIR/arc-consumed-in-looped-closure.rs:30:22
3+
|
4+
LL | let results = Arc::new(Mutex::new(Vec::new()));
5+
| ------- move occurs because `results` has type `Arc<std::sync::Mutex<Vec<i32>>>`, which does not implement the `Copy` trait
6+
...
7+
LL | for i in 0..20 {
8+
| -------------- inside of this loop
9+
LL | // let results = Arc::clone(&results); // Forgot this.
10+
LL | pool.execute(move || {
11+
| ^^^^^^^ value moved into closure here, in previous iteration of loop
12+
...
13+
LL | let mut r = results.lock().unwrap();
14+
| ------- use occurs due to use in closure
15+
|
16+
help: consider cloning the value before moving it into the closure
17+
|
18+
LL ~ let value = results.clone();
19+
LL ~ pool.execute(move || {
20+
LL |
21+
LL |
22+
LL ~ let mut r = value.lock().unwrap();
23+
|
24+
25+
error: aborting due to 1 previous error
26+
27+
For more information about this error, try `rustc --explain E0382`.

tests/ui/moves/nested-loop-moved-value-wrong-continue.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ fn foo() {
77
//~^ NOTE this reinitialization might get skipped
88
//~| NOTE move occurs because `foo` has type `String`
99
//~| NOTE inside of this loop
10-
//~| HELP consider moving the expression out of the loop
11-
//~| NOTE in this expansion of desugaring of `for` loop
1210
//~| NOTE
1311
//~| NOTE
1412
baz.push(foo);
@@ -35,16 +33,14 @@ fn main() {
3533
//~| NOTE
3634
for bar in &bars {
3735
//~^ NOTE inside of this loop
38-
//~| HELP consider moving the expression out of the loop
39-
//~| NOTE in this expansion of desugaring of `for` loop
4036
//~| NOTE
4137
if foo == *bar {
4238
baz.push(foo);
4339
//~^ NOTE value moved here
4440
//~| HELP consider cloning the value
4541
continue;
4642
//~^ NOTE verify that your loop breaking logic is correct
47-
//~| NOTE this `continue` advances the loop at line 36
43+
//~| NOTE this `continue` advances the loop at line 34
4844
}
4945
}
5046
qux.push(foo);

tests/ui/moves/nested-loop-moved-value-wrong-continue.stderr

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0382]: use of moved value: `foo`
2-
--> $DIR/nested-loop-moved-value-wrong-continue.rs:21:14
2+
--> $DIR/nested-loop-moved-value-wrong-continue.rs:19:14
33
|
44
LL | for foo in foos { for bar in &bars { if foo == *bar {
55
| --- ---------------- inside of this loop
@@ -14,29 +14,20 @@ LL | qux.push(foo);
1414
| ^^^ value used here after move
1515
|
1616
note: verify that your loop breaking logic is correct
17-
--> $DIR/nested-loop-moved-value-wrong-continue.rs:17:9
17+
--> $DIR/nested-loop-moved-value-wrong-continue.rs:15:9
1818
|
1919
LL | for foo in foos { for bar in &bars { if foo == *bar {
2020
| --------------- ----------------
2121
...
2222
LL | continue;
23-
| ^^^^^^^^ this `continue` advances the loop at $DIR/nested-loop-moved-value-wrong-continue.rs:6:23: 20:8
24-
help: consider moving the expression out of the loop so it is only moved once
25-
|
26-
LL ~ for foo in foos { let mut value = baz.push(foo);
27-
LL ~ for bar in &bars { if foo == *bar {
28-
LL |
29-
...
30-
LL |
31-
LL ~ value;
32-
|
23+
| ^^^^^^^^ this `continue` advances the loop at $DIR/nested-loop-moved-value-wrong-continue.rs:6:23: 18:8
3324
help: consider cloning the value if the performance cost is acceptable
3425
|
3526
LL | baz.push(foo.clone());
3627
| ++++++++
3728

3829
error[E0382]: use of moved value: `foo`
39-
--> $DIR/nested-loop-moved-value-wrong-continue.rs:50:18
30+
--> $DIR/nested-loop-moved-value-wrong-continue.rs:46:18
4031
|
4132
LL | for foo in foos {
4233
| ---
@@ -54,7 +45,7 @@ LL | qux.push(foo);
5445
| ^^^ value used here after move
5546
|
5647
note: verify that your loop breaking logic is correct
57-
--> $DIR/nested-loop-moved-value-wrong-continue.rs:45:17
48+
--> $DIR/nested-loop-moved-value-wrong-continue.rs:41:17
5849
|
5950
LL | for foo in foos {
6051
| ---------------
@@ -63,16 +54,7 @@ LL | for bar in &bars {
6354
| ----------------
6455
...
6556
LL | continue;
66-
| ^^^^^^^^ this `continue` advances the loop at line 36
67-
help: consider moving the expression out of the loop so it is only moved once
68-
|
69-
LL ~ let mut value = baz.push(foo);
70-
LL ~ for bar in &bars {
71-
LL |
72-
...
73-
LL | if foo == *bar {
74-
LL ~ value;
75-
|
57+
| ^^^^^^^^ this `continue` advances the loop at line 34
7658
help: consider cloning the value if the performance cost is acceptable
7759
|
7860
LL | baz.push(foo.clone());

0 commit comments

Comments
 (0)