Rollup merge of #149863 - estebank:issue-149861, r=mati865
Do not suggest moving expression out of for loop when hitting `break` from desugaring Fix rust-lang/rust#149861.
This commit is contained in:
commit
eb309e5182
6 changed files with 74 additions and 40 deletions
|
|
@ -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) => {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
37
tests/ui/moves/arc-consumed-in-looped-closure.rs
Normal file
37
tests/ui/moves/arc-consumed-in-looped-closure.rs
Normal 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);
|
||||
});
|
||||
}
|
||||
}
|
||||
27
tests/ui/moves/arc-consumed-in-looped-closure.stderr
Normal file
27
tests/ui/moves/arc-consumed-in-looped-closure.stderr
Normal 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`.
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue