Skip to content

Use of moved value error in the for iterator could give a hint about borrowing #25534

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
lifthrasiir opened this issue May 17, 2015 · 2 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-diagnostics Working group: Diagnostics

Comments

@lifthrasiir
Copy link
Contributor

fn main() {
    let a = vec![1, 2, 3];
    for i in a {
        for j in a {
            println!("{} * {} = {}", i, j, i * j);
        }
    }
}

currently gives:

<anon>:4:18: 4:19 error: use of moved value: `a`
<anon>:4         for j in a {
                          ^
note: in expansion of for loop expansion
<anon>:4:9: 6:10 note: expansion site
note: in expansion of for loop expansion
<anon>:3:5: 7:6 note: expansion site
<anon>:3:14: 3:15 note: `a` moved here because it has type `collections::vec::Vec<i32>`, which is non-copyable
<anon>:3     for i in a {
                      ^
note: in expansion of for loop expansion
<anon>:3:5: 7:6 note: expansion site
error: aborting due to previous error

Of course, we all know that for i in &a etc. is correct here, but this is not very obvious to beginners. We may want to give a contextual hint for "use of moved value" errors among others---probably as a second note following the original move.

(Feel free to make this a metabug if there are other such examples.)

@steveklabnik steveklabnik added the A-diagnostics Area: Messages for errors, warnings, and lints label May 18, 2015
@Densaugeo
Copy link

This would definitely help. I couldn't figure that error out until I found this post.

@steveklabnik steveklabnik added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Mar 9, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jul 22, 2017
@estebank
Copy link
Contributor

Triage: no change, same output with new style. It should check wether the first move happened in a for loop and suggest changing both places for borrows.

error[E0382]: use of moved value: `a`
 --> src/main.rs:4:18
  |
3 |     for i in a {
  |              - value moved here
  |              |
  |              help: consider borrowing `a` instead: `&a`
4 |         for j in a {
  |                  ^ value used here after move
  |                  |
  |                  help: consider borrowing `a` instead: `&a`
  = note: move occurs because `a` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait

Another case to consider is when moving after a borrow, which should also suggest borrowing instead of moving:

error[E0505]: cannot move out of `a` because it is borrowed
 --> src/main.rs:4:18
  |
3 |     for i in &a {
  |               - borrow of `a` occurs here
4 |         for j in a {
  |                  ^ move out of `a` occurs here
  |                  |
  |                  help: consider borrowing `a` instead: `&a`

error[E0382]: use of moved value: `a`
 --> src/main.rs:4:18
  |
4 |         for j in a {
  |                  ^ value moved here in previous iteration of loop
  |                  |
  |                  help: consider borrowing `a` instead: `&a`
  = note: move occurs because `a` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait

error: aborting due to 2 previous errors

Also, the second error should probably avoid showing multiple borrow errors for the same span, as fixing one would also fix the other.

@estebank estebank added E-needs-mentor WG-diagnostics Working group: Diagnostics labels Oct 13, 2017
Mark-Simulacrum added a commit to Mark-Simulacrum/rust that referenced this issue Mar 23, 2019
When moving out of a for loop head, suggest borrowing it

When encountering code like the following, suggest borrowing the for loop
head to avoid moving it into the for loop pattern:

```
fn main() {
    let a = vec![1, 2, 3];
    for i in &a {
        for j in a {
            println!("{} * {} = {}", i, j, i * j);
        }
    }
}
```

Fix rust-lang#25534.
bors added a commit that referenced this issue Mar 25, 2019
When moving out of a for loop head, suggest borrowing it

When encountering code like the following, suggest borrowing the for loop
head to avoid moving it into the for loop pattern:

```
fn main() {
    let a = vec![1, 2, 3];
    for i in &a {
        for j in a {
            println!("{} * {} = {}", i, j, i * j);
        }
    }
}
```

Fix #25534.
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-diagnostics Working group: Diagnostics
Projects
None yet
Development

No branches or pull requests

5 participants