Skip to content

Iterating a vector that needs to have mutable references error is a bit cryptic and leads down wrong path #114311

Closed
@drebbe-intrepid

Description

@drebbe-intrepid

Code

struct Test {
    a: u32
}

impl Test {
    pub fn add(&mut self, value: u32) {
        self.a += value;
    }
    
    pub fn print_value(&self) {
        println!("Value of a is: {}", self.a);
    }
}

fn main() {
    let mut tests = Vec::new();
    // fill the vector with some Test structs
    for i in 0..=10 {
        tests.push(Test {a: i});
    }
    
    /*
    // First Error: error[E0596]: cannot borrow `test` as mutable, as it is not declared as mutable
    for test in tests {
        test.add(2);
    }
    */
    
    /*
    // Second Error: error[E0382]: borrow of moved value: `tests`
    for mut test in tests {
        test.add(2);
    }
    */
    
    /*
    // Third Error: error[E0596]: cannot borrow `*test` as mutable, as it is behind a `&` reference
    for mut test in &tests {
        test.add(2);
    }
    */
    
    /*
    // Another dead end: error[E0596]: cannot borrow `*test` as mutable, as it is behind a `&` reference
    for test in &tests {
        test.add(2);
    }
    */
    
    // error above should have a recommendation to make tests a mutable reference
    for test in &mut tests {
        test.add(2);
    }

    
    for test in &tests {
        test.print_value();
    }
}

Current output

First Error:

error[E0596]: cannot borrow `test` as mutable, as it is not declared as mutable
  --> src/main.rs:25:9
   |
25 |         test.add(2);
   |         ^^^^^^^^^^^ cannot borrow as mutable
   |
help: consider changing this to be mutable
   |
24 |     for mut test in tests {
   |         +++

Second Error:

error[E0382]: borrow of moved value: `tests`
  --> src/main.rs:51:17
   |
16 |     let mut tests = Vec::new();
   |         --------- move occurs because `tests` has type `Vec<Test>`, which does not implement the `Copy` trait
...
31 |     for mut test in tests {
   |                     ----- `tests` moved due to this implicit call to `.into_iter()`
...
51 |     for test in &mut tests {
   |                 ^^^^^^^^^^ value borrowed here after move
   |
note: `into_iter` takes ownership of the receiver `self`, which moves `tests`
  --> /rustc/8ede3aae28fe6e4d52b38157d7bfe0d3bceef225/library/core/src/iter/traits/collect.rs:271:18
help: consider iterating over a slice of the `Vec<Test>`'s content to avoid moving into the `for` loop
   |
31 |     for mut test in &tests {
   |                     +

Third Error:

warning: variable does not need to be mutable
  --> src/main.rs:38:9
   |
38 |     for mut test in &tests {
   |         ----^^^^
   |         |
   |         help: remove this `mut`
   |
   = note: `#[warn(unused_mut)]` on by default

error[E0596]: cannot borrow `*test` as mutable, as it is behind a `&` reference
  --> src/main.rs:39:9
   |
38 |     for mut test in &tests {
   |                     ------ this iterator yields `&` references
39 |         test.add(2);
   |         ^^^^^^^^^^^ `test` is a `&` reference, so the data it refers to cannot be borrowed as mutable

Another dead-end:

error[E0596]: cannot borrow `*test` as mutable, as it is behind a `&` reference
  --> src/main.rs:46:9
   |
45 |     for test in &tests {
   |                 ------ this iterator yields `&` references
46 |         test.add(2);
   |         ^^^^^^^^^^^ `test` is a `&` reference, so the data it refers to cannot be borrowed as mutable

Desired output

error[E0596]: cannot borrow `test` as mutable, as it is not declared as mutable
  --> src/main.rs:25:9
   |
25 |         test.add(2);
   |         ^^^^^^^^^^^ cannot borrow as mutable
   |
help: consider changing this to be a `&` mutable reference
   |
24 |     for mut test in &mut tests {
   |                     ++++

Rationale and extra context

The first error compiler messages leads to the second error, which in turn leads to the third error which ends up not solving the actual issue.

I'm not sure if the desired output is the best way to go but I believe I would have fixed the issue a lot faster if I had that instead.

Other cases

No response

Anything else?

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=e7a08793435e70676d81d98c826b0286

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsT-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