Skip to content

Improve error message for struct element borrow by closure #57141

Open
@BartMassey

Description

@BartMassey

Consider this small example.

The code:

struct S { x: f32, y: f32 }

fn main() {
    let mut s = S { x: 1.0, y: 2.0 };
    let eval = |x| {
        x + s.y
    };
    s.x = eval(s.x);
    s.x = eval(s.x);
    println!("{} {}", s.x, s.y);
}

The compiler reports:

error[E0506]: cannot assign to `s.x` because it is borrowed
 --> src/main.rs:8:5
  |
5 |     let eval = |x| {
  |                --- borrow of `s.x` occurs here
6 |         x + s.y
  |             - borrow occurs due to use in closure
7 |     };
8 |     s.x = eval(s.x);
  |     ^^^^^^^^^^^^^^^ assignment to borrowed `s.x` occurs here
9 |     s.x = eval(s.x);
  |           ---- borrow later used here

error: aborting due to previous error

The compiler is correct in that s is borrowed by the eval closure, so it can't be mutated afterward. However, s.x is never borrowed by anything, so the error message is pretty confusing. In particular, "--- borrow of s.x occurs here" just looks wrong. I'm not sure whether the compiler is just accidentally pointing at the parameter (which is an ordinary f32) or whether it has gotten confused.

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-editionDiagnostics: An error or lint that should account for edition differences.P-lowLow 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