Skip to content

Possibly confusing error message when deref/deref_mut are used. #58843

Open

Description

Beginners can be confused when deref and deref_mut are called implicitely:

In this given code:

struct Foo {
    a: Vec<i32>,
    b: Vec<i32>,
}

fn add(foo: std::sync::Mutex<Foo>) {
    let f = foo.lock().unwrap();

    for i in &mut f.a {
        for j in &f.b {
            *i += *j;
        }
    }
}

The error message is not the clearest:

error[E0502]: cannot borrow `f` as immutable because it is also borrowed as mutable
  --> src/lib.rs:10:19
   |
9  |     for i in &mut f.a {
   |              --------
   |              |    |
   |              |    mutable borrow occurs here
   |              mutable borrow used here, in later iteration of loop
10 |         for j in &f.b {
   |                   ^ immutable borrow occurs here

The users could not understand that the borrows are done by deref and deref_mut, since the calls are implicit. They could think that, for an unknown reason, the borrow checker does not understand that the fields are disjoint.

I think that it would be an improvement if the compiler added that the implicit call to deref/deref_mut is responsible of the borrowing:

error[E0502]: cannot borrow `f` as immutable because it is also borrowed as mutable
  --> src/lib.rs:10:19
   |
9  |     for i in &mut f.a {
   |              --------
   |              |    |
   |              |    mutable borrow occurs here due to a call to `Deref::deref`
   |              mutable borrow used here, in later iteration of loop
10 |         for j in &f.b {
   |                   ^ immutable borrow occurs here due to a call to `DerefMut::deref_mut`

This could be even better if the compiler gave the solution:

You can call `DerefMut::deref_mut` before borrowing the fields:
  --> src/lib.rs:8:1
7  |    let mut f = foo.lock().unwrap();
   |    let f = DerefMut::deref_mut(&mut f);
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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.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