Description
Given the following code:
use std::collections::HashMap;
fn main() {
let mut vec = vec![0, 1, 2, 3, 4];
let mut map = HashMap::<&i32, &str>::new();
for key in &vec {
map.insert(key, "value");
}
vec.push(5);
}
The compiler will complain with the following error message:
error[E0502]: cannot borrow `vec` as mutable because it is also borrowed as immutable
--> /tmp/test_borrow_message.rs:11:5
|
7 | for key in &vec {
| --- immutable borrow occurs here
...
11 | vec.push(5);
| ^^^ mutable borrow occurs here
12 | }
| - immutable borrow ends here
error: aborting due to previous error
While the borrow error is expected, the message seems pretty unclear to me.
Removing/commenting the map.insert(key, "value");
line will allow rustc to compile the file, which shows the problem isn't really exactly with the borrow happening at line 7 (for loop), but with the fact that the borrow is then extended to the lifetime of the map
variable.
This can be verified with the following code which works because the map
variable is gone by the time we need to mutable borrow again:
use std::collections::HashMap;
fn main() {
let mut vec = vec![0, 1, 2, 3, 4];
{
let mut map = HashMap::<&i32, &str>::new();
for key in &vec {
map.insert(key, "value");
}
}
vec.push(5);
}
It feels like the compiler should be clearer as to where the borrow is actually "stored". It's able to show that the borrow ends when map
goes away, so I feel it should be clearer that the borrow issue stems from the map.insert(key, "value");
line, which extends the borrow's "lifetime" to the lifetime of map
(this error is output by rust 1.4.0)