- Notifications
You must be signed in to change notification settings - Fork 13.9k
Open
Labels
A-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsC-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Description
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); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Stargateur, shepmaster and matklad
Metadata
Metadata
Assignees
Labels
A-diagnosticsArea: Messages for errors, warnings, and lintsArea: Messages for errors, warnings, and lintsC-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.