Description
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]`