Zotta
Zotta

Reputation: 2603

Rust error E0506: Variable still borrowed after return statement

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

Answers (0)

Related Questions