I just started out with Rust. I have some trouble understanding mutable and immutable borrows with respect to this snippet of code. Here is the code I am testing.
fn main() {
let mut list = vec![1,2,3,4,5,6];
let i = 2;
list[list[i]] = list[list[i-1]];
}
On compiling this, I get the following error:
error[E0502]: cannot borrow `list` as immutable because it is also borrowed as mutable
--> src/main.rs:4:7
|
4 | list[list[i]] = list[list[i-1]];
| -----^^^^----
| | |
| | immutable borrow occurs here
| mutable borrow occurs here
| mutable borrow later used here
error: aborting due to previous error
When I replace the snippet above with this code instead,
fn main() {
let mut list = vec![1,2,3,4,5,6];
let i = 2;
let index = list[i];
list[index] = list[list[i-1]];
}
the code compiles and executes fine.
My question is why is the compiler not flagging this as an error like this?
5 | list[index] = list[list[i-1]];
| --------------| |
| | | immutable borrow occurs here
| | immutable borrow occurs here
| mutable borrow occurs here
| mutable borrow later used here
Isin't the right hand side of the assignment an immutable borrow? Why only flag the first code snippet as an error?
Does Rust have something like happens-before or sequenced before relationship in C++ which ensures that the immutable borrow on the right hand side is sequenced before the mutable borrow on the left hand side and hence it is not an error?
If the answer to the previous question is yes, then why can't the compiler sequence list[list[i]] internally as let tmp = list[i]; list[tmp]=...?
list[list[0]] = 1doesn't compile but*list.index_mut(*list.index(0)) = 1;does. - orlpIndex(Mut) traits, but is built in to the compiler, may also be relevant - that should usually be unobservable but I think it can make a difference in certain obscure cases like this - trentcl