Reputation: 2603
Why does the Rust compiler sometimes think that a value is still borrowed by a return statement in code after the return
statement? How to avoid the E0506 error in this case?
Here is some sample code:
use std::vec::Vec;
pub struct CachedValue {
pub i: usize,
pub v: i32
}
pub fn get_or_compute<'c>(cached_values: &'c mut Vec<Option<CachedValue>>, i: usize) -> Result<&'c i32, ()> {
let cache_size = cached_values.len();
let slot = &mut cached_values[i%cache_size];
if let Some(cached_value) = slot {
// If you comment out the if statement, but not the return statement,
// then the code compiles.
if cached_value.i == i {
return Ok(&cached_value.v);
}
}
// It is not possible for `slot` still be borrowed by something else here,
// but the compiler thinks it is.
let computed = 42;
*slot = Some(CachedValue { i: i, v: computed });
return Ok(&slot.as_ref().unwrap().v);
}
Compiler output:
error[E0506]: cannot assign to `*slot` because it is borrowed
--> <source>:20:5
|
8 | pub fn get_or_compute<'c>(cached_values: &'c mut Vec<Option<CachedValue>>, i: usize) -> Result<&'c i32, ()> {
| -- lifetime `'c` defined here
...
11 | if let Some(cached_value) = slot {
| ------------ `*slot` is borrowed here
...
14 | return Ok(&cached_value.v);
| ------------------- returning this value requires that `slot.0` is borrowed for `'c`
...
20 | *slot = Some(CachedValue { i: i, v: computed });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*slot` is assigned to here but it was already borrowed
error: aborting due to 1 previous error
Upvotes: 0
Views: 38