Skip to content

Confusing error message with moving a value within a nested for loop #92531

Closed
@ilyvion

Description

@ilyvion

I had code similar to the below (which is a minimal reproduction version of the original code), and its error was very confusing to me, enough so that I had to ask about what was wrong with it on the Rust discord, and even then it took a little while before anyone could get through to me what was even wrong.

Given the following code: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=c437992df178c2e794b09b37cc3b2ea3

let foos = vec![String::from("hello"), String::from("world")];
let bars = vec!["world"];

let mut baz = vec![];
let mut qux = vec![];

for foo in foos {
    for bar in &bars {
        if foo == *bar {
            baz.push(foo);
            continue;
        }
    }
    
    qux.push(foo);
}

The current output is:

error[E0382]: borrow of moved value: `foo`
  --> src/main.rs:10:16
   |
8  |     for foo in foos {
   |         ---
   |         |
   |         this reinitialization might get skipped
   |         move occurs because `foo` has type `String`, which does not implement the `Copy` trait
9  |         for bar in &bars {
10 |             if foo == *bar {
   |                ^^^ value borrowed here after move
11 |                 baz.push(foo);
   |                          --- value moved here, in previous iteration of loop

The problem was that I meant to continue the outer loop, but I had forgotten that I was inside an inner loop. What made it all the more confusing is that it points to foo in the outer loop and says "this reinitialization might get skipped," which baffled me, because I couldn't ever imagine a loop variable not being reinitialized when the next iteration comes around.

So the combination of "value moved here, in previous iteration of loop" combined with "this reinitialization might get skipped" made no sense to me.

I'm not really sure how this could be improved, but the fact that there are two loops involved makes this diagnostic confusing in my opinion. It might make sense to detect that such a situation is going on and be more careful about the wording, by saying something like "in previous iteration of inner loop."

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-borrow-checkerArea: The borrow checkerA-diagnosticsArea: Messages for errors, warnings, and lintsC-enhancementCategory: An issue proposing an enhancement or a PR with one.D-terseDiagnostics: An error or lint that doesn't give enough information about the problem at hand.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions