Open
Description
openedon Mar 1, 2019
Beginners can be confused when deref
and deref_mut
are called implicitely:
- https://stackoverflow.com/questions/47060266/error-while-trying-to-borrow-2-fields-from-a-struct-wrapped-in-refcell
- https://stackoverflow.com/questions/54942045/accessing-two-vectors-in-a-struct-locked-by-a-mutex
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