Reputation: 8467
There are a lot of answers for the questions about Rust's error[E0502]
, but I can't really understand one particular case. I have a struct
and it's impl
method that goes like this:
struct Test {
test_vec: Vec<i32>,
}
impl Test {
// other methods...
fn test(&mut self) -> i32 {
self.test_vec.swap(0, self.test_vec.len() - 1);
// other operations...
}
}
Trying to compile that immediately results in error:
error[E0502]: cannot borrow
self.test_vec
as immutable because it is also borrowed as mutable
self.test_vec.swap(0, self.test_vec.len() - 1);
------------- ---- ^^^^^^^^^^^^^ immutable borrow occurs here
| |
| mutable borrow later used by call
mutable borrow occurs here
Can anyone please explain why? It doesn't really look like I'm trying to borrow self.test_vec
there, I'm passing the usize
type result of a len()
call. On the other hand:
fn test(&mut self) -> i32 {
let last_index = self.test_vec.len() - 1;
self.test_vec.swap(0, last_index);
// other operations...
}
Using temporary variable, it works as expected, makes me thinking that len()
call is somehow evaluated after it gets to to the swap
, and thus being borrowed? Am I not seeing something because of the syntax sugar?
Upvotes: 2
Views: 753
Reputation: 2507
You have to think of this in the way the compiler does. When you write:
self.test_vec.swap(0, self.test_vec.len() - 1);
What the compiler sees:
let temp1 = &mut self.test_vec; // Mutable borrow of self.test_vec
let temp2 = &self.test_vec; // (ERROR!) Shared borrow of self.test_vec for use on getting the length
let temp3 = Vec::len(temp2) - 1;
Vec::swap(temp1, 0, temp3);
As you can see, you are borrowing self.test_vec
mutably first, and then trying to get the length, which is another borrow. Since the first borrow is mutable and still in effect, the second borrow is illegal.
When you use a temporary variable, you are effectively reordering your borrows and since self.test_vec.len()
terminates the borrow before the next mutable borrow, there are no conflicts.
You can argue the compiler should be able to see that your code can be correct (if interpreted with in the right way), but the compiler is clearly not smart enough yet to do so.
Upvotes: 1