rustlifetimerwlock

Why can't I return a nested `RwLockReadGuard` from a function?


I have greatly simplified my specific problem to the example below:

struct MyStruct {
    my_lock: RwLock<RwLock<u8>>
}

impl MyStruct {
    async fn my_function(&self) -> RwLockReadGuard<u8> {
        let outer_guard = self.my_lock.read().await;
        let inner_guard = outer_guard.read().await;
        return inner_guard;
    }
}

I'm getting the following error:

error[E0515]: cannot return value referencing local variable `outer_guard`
  --> src/geolocations/geocode/client.rs:99:10
   |
98 |         let inner_guard = outer_guard.read().await;
   |                           ----------- `outer_guard` is borrowed here
99 |         return inner_guard;
   |                ^^^^^^^^^^^ returns a value referencing data owned by the current function

In my mind, the lifetime of inner_guard is bound to the lifetime of my_lock which is bound to the lifetime of self. Why does Rust care at all about the fact that outer_guard is bound to the scope of the function with regards to returning inner_guard if the two are not bound to each other?

How can I return the second RwLockReadGuard<u8> from the function? Or at a minimum, a reference to the u8 value it's guarding?


Solution

  • Depending on whether you ever need a &mut to the inner data, you can use one of these approaches:

    Both approaches provide a kind of "snapshot" capability where accessing an entry value does not require holding a lock on the map itself. In particular, when using the first approach, tasks that take an Arc can use a consistent point-in-time view of the cached data that will not change, even if the map is updated with a new value.

    You might also consider looking into the moka crate, which provides implementations of both synchronous and asynchronous caching maps, both of which handle locking and eviction for you.