Skip to content

More precisely point out what is immutable, in E0596 "cannot borrow data in a & reference as mutable" #113842

Open
@kpreid

Description

@kpreid

Code

mod some_library {
    pub fn foo(_: &mut [i32]) {}
    pub fn bar<'a>() -> &'a [i32] {
        &[]
    }
    pub fn bar_mut<'a>() -> &'a mut [i32] {
        &mut []
    }
}

fn main() {
    some_library::foo(&mut some_library::bar());
}

Current output

error[E0596]: cannot borrow data in a `&` reference as mutable
  --> src/main.rs:12:23
   |
12 |     some_library::foo(&mut some_library::bar());
   |                       ^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable

Desired output

error[E0596]: cannot borrow data in a `&` reference as mutable
  --> src/main.rs:12:23
   |
12 |     some_library::foo(&mut some_library::bar());
   |                            ^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable

help: `some_library::bar()` is of type `&[i32]`, which is an immutable reference
help: `some_library::bar_mut()` might be the operation you need

Rationale and extra context

The current output is confusing because it does not indicate which part of the input is the source of the immutability, and especially because the span contains the &mut (which in this case is irrelevant, but is often attempted and may be needed to trigger DerefMut).

Many newcomers to Rust are not yet familiar with the idea that in order to get mutable access to some data, every part of the path by which they get that data must be mutable.

I have proposed that the compiler suggest calling bar_mut() per the naming convention, but this is questionable since the function might have different semantics, and it is secondary to the main issue here of pointing to the immutability clearly.

Other cases

Without the &mut,

    some_library::foo(some_library::bar());

the error is much clearer, but completely different since no reborrowing is involved:

error[E0308]: mismatched types
  --> src/main.rs:12:23
   |
12 |     some_library::foo(some_library::bar());
   |     ----------------- ^^^^^^^^^^^^^^^^^^^ types differ in mutability
   |     |
   |     arguments to this function are incorrect
   |
   = note: expected mutable reference `&mut [i32]`
                      found reference `&[i32]`

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