Borrowed value does not live long enough (value from generic passed to function)

It's all day I'm stuck on this:

    pub fn load<'k, K, V>(&self, key: K) -> Result<Option<V>, Error> where
        K: 'k + Key<'k>,
        V: 'k + Persistent + Debug + Serialize + for<'de> Deserialize<'de>,
    {
        let bucket = self.store
            .bucket::<K,Bincode<V>>(Some(V::bucket_name()))?;
        bucket
            .get(key)?
            .map_or(Ok(None), |data| Ok(Some(data.0)))
    }

rust compiler output:

error[E0597]: `bucket` does not live long enough
  --> src/persist.rs:35:9
   |
29 |       pub fn load<'k, K, V>(&self, key: K) -> Result<Option<V>, Error> where
   |                   -- lifetime `'k` defined here
...
35 |           bucket
   |           -^^^^^
   |           |
   |  _________borrowed value does not live long enough
   | |
36 | |             .get(key)?
   | |_____________________- argument requires that `bucket` is borrowed for `'k`
37 |               .map_or(Ok(None), |data| Ok(Some(data.0)))
38 |       }
   |       - `bucket` dropped here while still borrowed

error: aborting due to previous error

For more information about this error, try `rustc --explain E0597`.
error: could not compile `disyer`

To learn more, run the command again with --verbose.

I tried almost everything even using Higher-Rank Trait Bounds (HRTBs) without success.

Replacing K with a concrete type (like &str) works perfectly but I want the method to work with generics (like the bucket.get() function I'm calling does).

The library I'm writing aims to be a simple wrapper around kv crate.

I think this is because Bucket<'a, _, _>::get requires &'a self instead of an unconstrained &self. Perhaps open an issue against the kv crate.

Is it necessary to tag types K and V with lifetime 'k here?

Looking at that crate as well, it's not clear to me why there is a lifetime at all on Bucket. I can't figure out what its purpose would be. Additionally it just seems to over constrain the interface as @quinedot points out.

I noticed the lifetime on the get() and contains() methods and I was asking myself why is there.
I will modify kv and possibly open a PR.
And obviously I'll update you!

Lifetime on get() and contains() was in fact useless: removing it fixed the problem:

    pub fn load<'a, K, V>(&self, key: K) -> Result<Option<V>, Error> where
        K: Key<'a>,
        V: Persistent + Debug + Serialize + for<'de> Deserialize<'de>,
    {
        let bucket = self.store
            .bucket::<K,Bincode<V>>(Some(V::bucket_name()))?;
        bucket
            .get(key)?
            .map_or(Ok(None), |data| Ok(Some(data.0)))
    }

Opened PR on kv:
https://github.com/zshipko/rust-kv/pull/19

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.