I know the general answer — You can only borrow mutably once or immutably many times, but not both. I want to know why this specific case is considered simultaneous borrowing.
I have the following code:
fn main() {
let mut v = vec![1, 2, 3, 4, 5];
let n = 3;
// checks on n and v.len() and whatever else...
let mut s = v[..n].to_vec();
for i in 0..n {
v[i + v.len() - n] = s[1];
}
}
which produces the following error under 1.36.0:
error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
--> src/main.rs:7:15
|
7 | v[i + v.len() - n] = s[1];
| ------^-----------
| | |
| | immutable borrow occurs here
| mutable borrow occurs here
| mutable borrow later used here
It seems that there is no way for the write to v[x]
to happen until x
is computed, by which time the immutable borrow will be complete. Since the ordering here is completely in series, why doesn't the compiler recognize the dependency and treat these as non-overlapping borrows? Put another way, is there any scenario where this could lead to an actual problem?
Marouane Fazouane suggested concurrency as a possibility, but I don't think this is the case. If there were another thread with a (presumably) mutable reference, it would be a violation to then call v.len()
, or to start v[...]
. Here, the compiler knows everything that's happening to v
— it's a local definition with no other calls. For me, the question is why is this simultaneous borrowing when there's no way for v[]
to happen until len()
returns. It's akin to v.mutable_call(v.immutable_call());
Incidentally, an earlier version of the compiler (1.28) gave an error that indicated the close bracket as the end of the mutable borrow, so it seemed order is based on the source order, and since the source has the two intermingled, they could be considered overlapping. If so, surely the compiler could improve this...right?
This seems closely related to Why is there a borrow error when no borrowing overlap is occurring?