Description
A newcomer to Rust may have some code that looks like this (playground):
struct Foo;
impl Foo {
fn foo(&mut self, _: f32) -> i32 { todo!() }
fn bar(&mut self) -> f32 { todo!() }
fn baz(&mut self) {
self.foo(self.bar());
}
}
Which you would think would work, since the call to self.foo()
happens after self.bar()
returns, and so they have unique access to self
. However, this desugars into something like this:
struct Foo;
impl Foo {
fn foo(&mut self, _: f32) -> i32 { todo!() }
fn bar(&mut self) -> f32 { todo!() }
fn baz(&mut self) {
Self::foo(&mut self, Self::bar(&mut self));
}
}
Which, due to something else in the Rust aliasing rules that can be confusing, means that there are actually two unique borrows of self
live at the same time, and produces this error:
Compiling playground v0.0.1 (/playground)
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/lib.rs:7:14
|
7 | self.foo(self.bar());
| ---- --- ^^^^ second mutable borrow occurs here
| | |
| | first borrow later used by call
| first mutable borrow occurs here
However, this error is confusing because the error is only visible when the code is desugared. Because of how the code is desugared, this code – which is functionally equivalent – compiles fine (playground):
struct Foo;
impl Foo {
fn foo(&mut self, _: f32) -> i32 { todo!() }
fn bar(&mut self) -> f32 { todo!() }
fn baz(&mut self) {
let temp = self.bar();
self.foo(temp);
}
}
Therefore I propose adding a help message to the error that suggests extracting the result into a temporary. Something like this:
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/lib.rs:7:14
|
7 | self.foo(self.bar());
| ---- --- ^^^^ second mutable borrow occurs here
| | |
| | first borrow later used by call
| first mutable borrow occurs here
|
= help: try assigning `self.bar()` to a variable and then call `self.foo()` with that variable
Cc @jyn514