diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index f8a6fafbe78ac..2999d1f2926cc 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -4521,7 +4521,9 @@ struct BreakFinder { impl<'hir> Visitor<'hir> for BreakFinder { fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) { match ex.kind { - hir::ExprKind::Break(destination, _) => { + hir::ExprKind::Break(destination, _) + if !ex.span.is_desugaring(DesugaringKind::ForLoop) => + { self.found_breaks.push((destination, ex.span)); } hir::ExprKind::Continue(destination) => { diff --git a/tests/ui/ergonomic-clones/closure/spawn-thread.edition2018.stderr b/tests/ui/ergonomic-clones/closure/spawn-thread.edition2018.stderr index ac8e1c5fa858d..4ac5dfb8d228a 100644 --- a/tests/ui/ergonomic-clones/closure/spawn-thread.edition2018.stderr +++ b/tests/ui/ergonomic-clones/closure/spawn-thread.edition2018.stderr @@ -12,16 +12,6 @@ LL | | drop((x.0, x.1, x.2)); | | --- use occurs due to use in closure LL | | }); | |_________- value moved here, in previous iteration of loop - | -help: consider moving the expression out of the loop so it is only moved once - | -LL ~ let mut value = std::thread::spawn(use || { -LL + -LL + drop((x.0, x.1, x.2)); -LL + }); -LL ~ for _ in 0..10 { -LL ~ let handler = value; - | error: aborting due to 1 previous error diff --git a/tests/ui/moves/arc-consumed-in-looped-closure.rs b/tests/ui/moves/arc-consumed-in-looped-closure.rs new file mode 100644 index 0000000000000..8700c78508476 --- /dev/null +++ b/tests/ui/moves/arc-consumed-in-looped-closure.rs @@ -0,0 +1,37 @@ +use std::thread; +use std::sync::{Arc, Mutex, Condvar}; +use std::collections::VecDeque; + +type Job = Box; + +struct ThreadPool { + workers: Vec>, + queue: Arc<()>, +} + +impl ThreadPool { + fn execute(&self, f: F) + where + F: FnOnce() + Send + 'static, + { + panic!() + } +} + +fn main() { + let results = Arc::new(Mutex::new(Vec::new())); //~ NOTE move occurs because + let pool = ThreadPool { + workers: vec![], + queue: Arc::new(()), + }; + + for i in 0..20 { //~ NOTE inside of this loop + // let results = Arc::clone(&results); // Forgot this. + pool.execute(move || { //~ ERROR E0382 + //~^ NOTE value moved into closure here, in previous iteration of loop + //~| HELP consider cloning the value before moving it into the closure + let mut r = results.lock().unwrap(); //~ NOTE use occurs due to use in closure + r.push(i); + }); + } +} diff --git a/tests/ui/moves/arc-consumed-in-looped-closure.stderr b/tests/ui/moves/arc-consumed-in-looped-closure.stderr new file mode 100644 index 0000000000000..47d6fd6cbad3b --- /dev/null +++ b/tests/ui/moves/arc-consumed-in-looped-closure.stderr @@ -0,0 +1,27 @@ +error[E0382]: use of moved value: `results` + --> $DIR/arc-consumed-in-looped-closure.rs:30:22 + | +LL | let results = Arc::new(Mutex::new(Vec::new())); + | ------- move occurs because `results` has type `Arc>>`, which does not implement the `Copy` trait +... +LL | for i in 0..20 { + | -------------- inside of this loop +LL | // let results = Arc::clone(&results); // Forgot this. +LL | pool.execute(move || { + | ^^^^^^^ value moved into closure here, in previous iteration of loop +... +LL | let mut r = results.lock().unwrap(); + | ------- use occurs due to use in closure + | +help: consider cloning the value before moving it into the closure + | +LL ~ let value = results.clone(); +LL ~ pool.execute(move || { +LL | +LL | +LL ~ let mut r = value.lock().unwrap(); + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/moves/nested-loop-moved-value-wrong-continue.rs b/tests/ui/moves/nested-loop-moved-value-wrong-continue.rs index 87800d314ed50..0cbb501a57641 100644 --- a/tests/ui/moves/nested-loop-moved-value-wrong-continue.rs +++ b/tests/ui/moves/nested-loop-moved-value-wrong-continue.rs @@ -7,8 +7,6 @@ fn foo() { //~^ NOTE this reinitialization might get skipped //~| NOTE move occurs because `foo` has type `String` //~| NOTE inside of this loop - //~| HELP consider moving the expression out of the loop - //~| NOTE in this expansion of desugaring of `for` loop //~| NOTE //~| NOTE baz.push(foo); @@ -35,8 +33,6 @@ fn main() { //~| NOTE for bar in &bars { //~^ NOTE inside of this loop - //~| HELP consider moving the expression out of the loop - //~| NOTE in this expansion of desugaring of `for` loop //~| NOTE if foo == *bar { baz.push(foo); @@ -44,7 +40,7 @@ fn main() { //~| HELP consider cloning the value continue; //~^ NOTE verify that your loop breaking logic is correct - //~| NOTE this `continue` advances the loop at line 36 + //~| NOTE this `continue` advances the loop at line 34 } } qux.push(foo); diff --git a/tests/ui/moves/nested-loop-moved-value-wrong-continue.stderr b/tests/ui/moves/nested-loop-moved-value-wrong-continue.stderr index 6ef1a4193b1ae..60be70007fbe2 100644 --- a/tests/ui/moves/nested-loop-moved-value-wrong-continue.stderr +++ b/tests/ui/moves/nested-loop-moved-value-wrong-continue.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `foo` - --> $DIR/nested-loop-moved-value-wrong-continue.rs:21:14 + --> $DIR/nested-loop-moved-value-wrong-continue.rs:19:14 | LL | for foo in foos { for bar in &bars { if foo == *bar { | --- ---------------- inside of this loop @@ -14,29 +14,20 @@ LL | qux.push(foo); | ^^^ value used here after move | note: verify that your loop breaking logic is correct - --> $DIR/nested-loop-moved-value-wrong-continue.rs:17:9 + --> $DIR/nested-loop-moved-value-wrong-continue.rs:15:9 | LL | for foo in foos { for bar in &bars { if foo == *bar { | --------------- ---------------- ... LL | continue; - | ^^^^^^^^ this `continue` advances the loop at $DIR/nested-loop-moved-value-wrong-continue.rs:6:23: 20:8 -help: consider moving the expression out of the loop so it is only moved once - | -LL ~ for foo in foos { let mut value = baz.push(foo); -LL ~ for bar in &bars { if foo == *bar { -LL | -... -LL | -LL ~ value; - | + | ^^^^^^^^ this `continue` advances the loop at $DIR/nested-loop-moved-value-wrong-continue.rs:6:23: 18:8 help: consider cloning the value if the performance cost is acceptable | LL | baz.push(foo.clone()); | ++++++++ error[E0382]: use of moved value: `foo` - --> $DIR/nested-loop-moved-value-wrong-continue.rs:50:18 + --> $DIR/nested-loop-moved-value-wrong-continue.rs:46:18 | LL | for foo in foos { | --- @@ -54,7 +45,7 @@ LL | qux.push(foo); | ^^^ value used here after move | note: verify that your loop breaking logic is correct - --> $DIR/nested-loop-moved-value-wrong-continue.rs:45:17 + --> $DIR/nested-loop-moved-value-wrong-continue.rs:41:17 | LL | for foo in foos { | --------------- @@ -63,16 +54,7 @@ LL | for bar in &bars { | ---------------- ... LL | continue; - | ^^^^^^^^ this `continue` advances the loop at line 36 -help: consider moving the expression out of the loop so it is only moved once - | -LL ~ let mut value = baz.push(foo); -LL ~ for bar in &bars { -LL | -... -LL | if foo == *bar { -LL ~ value; - | + | ^^^^^^^^ this `continue` advances the loop at line 34 help: consider cloning the value if the performance cost is acceptable | LL | baz.push(foo.clone());