This compiles fine, but if you switch the commented out parts, you get:
error[E0502]: cannot borrow `split` as immutable because it is also borrowed as mutable
--> src/main.rs:21:15
|
20 | if let Some(ref mut one) = split.one {
| ----- mutable borrow occurs here
21 | read(&split.two);
| ^^^^^ immutable borrow occurs here
22 | *one = NotCopy;
| -------------- mutable borrow later used here
The reason this does not error in the original case is that Rust is aware of the semantics of &mut T's DerefMut and can reason about splitting borrows, however it is not aware of the semantics of RefMut<T>'s DerefMut and &split.two is able to read from split.one in a safely-written DerefMut impl.
The fix is to convert the RefMut<T> into an &mut T, via &mut *split before doing any of reads or writes.
One typically expects splitting mutable borrows to work in Rust, so it's weird when it doesn't. It would be nice if the compiler could detect when a situation is one of splitting borrows through a DerefMut impl and make the appropriate suggestion.
(Playground)
This compiles fine, but if you switch the commented out parts, you get:
The reason this does not error in the original case is that Rust is aware of the semantics of
&mut T
'sDerefMut
and can reason about splitting borrows, however it is not aware of the semantics ofRefMut<T>
'sDerefMut
and&split.two
is able to read fromsplit.one
in a safely-writtenDerefMut
impl.The fix is to convert the
RefMut<T>
into an&mut T
, via&mut *split
before doing any of reads or writes.One typically expects splitting mutable borrows to work in Rust, so it's weird when it doesn't. It would be nice if the compiler could detect when a situation is one of splitting borrows through a DerefMut impl and make the appropriate suggestion.