Do not suggest moving expression out of for loop when hitting break from desugaring

This commit is contained in:
Esteban Küber 2025-12-10 20:20:22 +00:00
parent f520900083
commit c60ed211d1
6 changed files with 74 additions and 40 deletions

View file

@ -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) => {

View file

@ -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

View file

@ -0,0 +1,37 @@
use std::thread;
use std::sync::{Arc, Mutex, Condvar};
use std::collections::VecDeque;
type Job = Box<dyn FnOnce() + Send + 'static>;
struct ThreadPool {
workers: Vec<thread::JoinHandle<()>>,
queue: Arc<()>,
}
impl ThreadPool {
fn execute<F>(&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);
});
}
}

View file

@ -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<std::sync::Mutex<Vec<i32>>>`, 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`.

View file

@ -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);

View file

@ -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());