Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

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

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in 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