1

I'm trying to implement a method that returns a RwLockReadGuard of a struct contained into a HashMap (itself in a RwLock).

The function below:

pub fn get_pair<'a>(&self, name: &str) -> Option<TradePairHandle> {
    if let Ok(ref pair) = self.pairs.read() {
        if let Some(p) = pair.get(name) {
            if let Ok(r) = p.read() {
                Some(TradePairHandle::new(r))
            } else {
                None
            }
        } else {
            None
        }
    } else {
        None
    }
}

raise the following compilation error:

error[E0515]: cannot return value referencing temporary value
  --> src/lib.rs:76:21
   |
73 |         if let Ok(ref pair) = self.pairs.read() {
   |                               ----------------- temporary value created here
...
76 |                     Some(TradePairHandle::new(r))
   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a value 

referencing data owned by the current function

How to do this the correct way?

There is the full Rust playground

pretzelhammer
  • 13,874
  • 15
  • 47
  • 98
Aurel
  • 479
  • 3
  • 13
  • Does this answer your question? [Is there any way to return a reference to a variable created in a function?](https://stackoverflow.com/questions/32682876/is-there-any-way-to-return-a-reference-to-a-variable-created-in-a-function) – L. Riemer Aug 20 '20 at 09:18
  • I m' afraid not, in my example the function don't return a reference – Aurel Aug 20 '20 at 09:21
  • Your function does return a reference, since `TradePairHandle` contains a `RwLockReadGuard`, which in turn holds a reference. However, it's not entirely accurate that the value that reference is pointing to is "created" inside your function. – Sven Marnach Aug 20 '20 at 09:24
  • The problem is rather that the outer lock, the one you grab in the first line of the function, will be released when returning from the function, so any reference you obtain from inside that lock will become invalid at that point. – Sven Marnach Aug 20 '20 at 09:26
  • Does this question help? [How to return a reference to a sub-value of a value that is under a mutex?](https://stackoverflow.com/q/40095383) – Sven Marnach Aug 20 '20 at 09:33
  • The easiest way would be to keep an `Arc` in your `TradePairHandle`. If you want it to stay unlocked, you can create a struct that will keep the `RwLockReadGuard` together with the `Arc`, using the `rental` crate to handle the self-reference. – Maya Aug 20 '20 at 14:17
  • @SvenMarnach Yes, this question kind of helped, thank you! But now, using owning_ref I have another error. I updated the question. – Aurel Aug 21 '20 at 11:24
  • @Aurel This is a completely separate question and should be asked as a new question. – Sven Marnach Aug 21 '20 at 12:52
  • 1
    @SvenMarnach ok, There it is: https://stackoverflow.com/questions/63523566/how-to-handle-cannot-infer-an-appropriate-lifetime-for-autoref-due-to-conflicti – Aurel Aug 21 '20 at 13:12

1 Answers1

2

Thanks to Sven Marnach, I tried a different approach with owning_ref crate. Now the method get_pair looks like this:

pub fn get_pair<'a, 'me: 'a>(
    &'me self,
    name: &str,
) -> RwLockReadGuardRef<'a, TradePairHashMap, Arc<RwLock<TradePair>>> {
    RwLockReadGuardRef::new(self.pairs.read().unwrap()).map(|pairs| pairs.get(name).unwrap())
}

And compile without errors. Thanks again!

Aurel
  • 479
  • 3
  • 13