Playground: https://play.rust-lang.org/?gist=0bde8d89f0ef683de58561b7cae3a096&version=nightly&backtrace=0
Code:
fn foo(b: &mut u64) {
let x = &mut b;
}
fn main() {
let mut x = 42;
foo(&mut x);
}
Current Error:
error: cannot borrow immutable argument `b` as mutable
--> <anon>:2:18
|
1 | fn foo(b: &mut u64) {
| - use `mut b` here to make mutable
2 | let x = &mut b;
| ^ cannot borrow mutably
error: aborting due to previous error
This error is confusing because:
Some of the immediate reactions in #rust include:
[21:48:05] <Ixrec> the message ought to be more like "cannot mutably borrow self because it's already a mutable reference"
[21:49:29] <misdreavus> "hint: self is already &mut Foo, do you mean to make a &mut &mut Foo?"
[21:52:00] <sebk> "self is already &mut" would have explained it for me
I think misdreavus' suggestion might be the best and/or simplest option.
As a beginner I was stuck on this problem, and only figured it out thanks to this github issue. This sentence was the hint I needed:
It explicitly suggests "adding more muts", when the correct solution is to remove the redundant "&mut".
b is an _immutable reference_ to a mutable u64, so it is really immutable as the error suggests. Nothing wrong there so far. The suggesting to add mut does indeed fix the compilation error.
We can elaborate with an extended example:
fn foo2<'a>(mut b: &'a mut u64, c: &'a mut u64) {
let x = &mut b; // allowed mutable ref to mutable ref,
// because 'mut b' above instead of 'b'.
*x = c; // allowed to deref the mutable ref.
}
fn foo3<'a>(mut b: &'a mut u64, c: &'a mut u64) {
b = c; // allowed because of 'mut b' above instead of just 'b'.
}
However to improve the error message, I don't know how the compiler would correctly do the intelligent guess on whether you really wanted a mutable reference to a mutable reference or just wanted to transfer ownership of an immutable reference. And if not, it would be too confusing to suggest both options, without losing the textual pointer that shows where to insert the mut. Consider this draft to illustrate:
error: cannot borrow immutable argument `b` as mutable (it's an immutable reference)`.
--> <anon>:2:18
|
1 | fn foo(b: &mut u64) {
| - use `mut b` here to make mutable (Or see another option below):
2 | let x = &mut b;
| ^ cannot borrow mutably, but can move it out by removing '&mut'.
error[E0596]: cannot borrow immutable argument `b` as mutable
--> src/main.rs:2:18
|
2 | let x = &mut b;
| ^ cannot borrow mutably
help: consider removing the `&mut`, as it is an immutable binding to a mutable reference
|
2 | let x = b;
| ^
Fixed by #51242.
Even tho this was closed, I seem to have encountered a very similar issue. Here's my output:
error[E0596]: cannot borrow `d` as mutable, as it is not declared as mutable
--> src\player.rs:20:45
|
14 | pub fn take_turn(p: &mut Player, m: &mut Vec<Meeple>, d: &mut Vec<Card>, f: &mut Vec<Card>) {
| - help: consider changing this to be mutable: `mut d`
...
20 | Org::State => state_turn(&mut p, &mut m, &mut d),
| ^^^^^^ cannot borrow as mutable
The solution was to remove all three &mut casts from line 20 (it was throwing 3 errors). The help output was, again, the opposite of what I had to do.
Most helpful comment
As a beginner I was stuck on this problem, and only figured it out thanks to this github issue. This sentence was the hint I needed: