Skip to content

Error message about immutable binding is not actually caused by a binding #49839

Closed

Description

@gdesmott

See the following code:

use std::collections::HashMap;

struct Test {
    v: u32,
}

fn main() {
    let mut map = HashMap::new();
    map.insert("a", Test { v: 0 });

    let values = map.values();
    for mut t in values {
        t.v += 1;
    }
}

It raises this compiler error:

error[E0594]: cannot assign to field t.v of immutable binding
--> /tmp/test.rs:14:9
|
14 | t.v += 1;
| ^^^^^^^^ cannot mutably borrow field of immutable binding

The fix is to use values_mut() instead of values().
But the error message is confusing as the problem here is not the binding as t itself is mut making it harder to debug for newcomers.

Activity

  1. added
    C-enhancementCategory: An issue proposing an enhancement or a PR with one.
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Jul 7, 2018
  2. mbrubeck commented on Jul 30, 2018

    @mbrubeck
    Contributor

    In Rust 1.23 and earlier, the error was:

    error[E0594]: cannot assign to immutable field `t.v`
      --> diag.rs:13:9
       |
    13 |         t.v += 1;
       |         ^^^^^^^^ cannot mutably borrow immutable field
    
    error: aborting due to previous error
    
  3. estebank commented on May 23, 2019

    @estebank
    Contributor

    Current output is slightly more misleading, but I think improving on this will be hard:

    error[E0594]: cannot assign to `t.v` which is behind a `&` reference
      --> src/main.rs:13:9
       |
    12 |     for mut t in values {
       |         ----- help: consider changing this to be a mutable reference: `&mut Test`
    13 |         t.v += 1;
       |         ^^^^^^^^ `t` is a `&` reference, so the data it refers to cannot be written
    
  4. estebank commented on May 25, 2019

    @estebank
    Contributor

    This overlaps slightly with #18150, but is more targeted, leaving open.

  5. added
    E-mediumCall for participation: Medium difficulty. Experience needed to fix: Intermediate.
    on May 25, 2019
  6. steveklabnik commented on May 12, 2020

    @steveklabnik
    Contributor

    Triage: no change

  7. sasurau4 commented on Jan 17, 2021

    @sasurau4
    Contributor

    I'll work on it. @rustbot calim

    current output is following.

    error[E0594]: cannot assign to `t.v` which is behind a `&` reference
      --> src/main.rs:13:9
       |
    12 |     for mut t in values {
       |                  ------ this iterator yields `&` references
    13 |         t.v += 1;
       |         ^^^^^^^^ `t` is a `&` reference, so the data it refers to cannot be written
    
  8. estebank commented on Jan 18, 2021

    @estebank
    Contributor

    @sasurau4 you might want to first focus on the case where the values() method has been called in the for loop as it will be easier to find the needed expressions and types to verify that values_mut is available. It would also be interesting to account for .iter() vs .iter_mut() as well as part of this work (it just adds another method to check for). For the exact case that is presented in the original report, you'll have to find where the binding that is in the iterator expression of the for loop comes from, which as things are today might be had (but not impossible for the common case) to do. I don't want to discourage you from tackling it if you desire to do so, but I do want you to know that so you don't get discouraged if you find it takes to long or becomes too hard. Handling the simpler cases has a lot of value on their own.

  9. sasurau4 commented on Jan 18, 2021

    @sasurau4
    Contributor

    @estebank Thanks for your advice! I was stuck on how to get the binding rhs expression for.
    I'll focus on the case you suggest 👍

  10. added a commit that references this issue on Feb 10, 2021
  11. estebank commented on Feb 14, 2021

    @estebank
    Contributor

    Thanks to @sasurau4 the output for the "inlined" case is now:

    error[E0594]: cannot assign to `t.v` which is behind a `&` reference
      --> src/main.rs:12:9
       |
    11 |     for mut t in map.values() {
       |                  ------------
       |                  |   |
       |                  |   help: use mutable method: `values_mut()`
       |                  this iterator yields `&` references
    12 |         t.v += 1;
       |         ^^^^^^^^ `t` is a `&` reference, so the data it refers to cannot be written
    

    The let values = map.values(); case still needs to be handled.

  12. added 2 commits that reference this issue on Aug 4, 2026
    7ef4a28
    02a459b
  13. added a commit that references this issue on Aug 5, 2026
    fb0023d
  14. added a commit that references this issue on Aug 5, 2026
    866a704
  15. added a commit that references this issue on Aug 17, 2026
    f47f6e7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsC-enhancementCategory: An issue proposing an enhancement or a PR with one.E-mediumCall for participation: Medium difficulty. Experience needed to fix: Intermediate.P-mediumMedium priorityT-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