Storing the return type of function called inside closure

I'm trying to store the result of a function call in r. However, I get that the type R may not live long enough

use std::sync::Arc;

pub type OnVirtualTunWrite = Arc<dyn Fn(Box<dyn FnOnce(&mut [u8])> , usize) -> Result<(), ()> + Send + Sync>;

struct A {
    on_virtual_tun_write: OnVirtualTunWrite
}

impl A {
    fn consume<R, F>(self, len: usize, f: F) -> Result<R,()>
    where
        F: FnOnce(&mut [u8]) ->  Result<R,()>,
    {
        let r: Result<R,()>;
        let result = (self.on_virtual_tun_write)(Box::new(|b: &mut [u8]| {
            r = f(b);
        }), len);
        r
    }
}

Error:

   Compiling playground v0.0.1 (/playground)
error[E0310]: the parameter type `R` may not live long enough
  --> src/lib.rs:15:50
   |
10 |     fn consume<R, F>(self, len: usize, f: F) -> Result<R,()>
   |                - help: consider adding an explicit lifetime bound...: `R: 'static`
...
15 |         let result = (self.on_virtual_tun_write)(Box::new(|b: &mut [u8]| {
   |                                                  ^^^^^^^^ ...so that the reference type `&mut std::result::Result<R, ()>` does not outlive the data it points at

error[E0310]: the parameter type `R` may not live long enough
  --> src/lib.rs:15:50
   |
10 |       fn consume<R, F>(self, len: usize, f: F) -> Result<R,()>
   |                  - help: consider adding an explicit lifetime bound...: `R: 'static`
...
15 |           let result = (self.on_virtual_tun_write)(Box::new(|b: &mut [u8]| {
   |  __________________________________________________^
16 | |             r = f(b);
17 | |         }), len);
   | |__________^ ...so that the type `[closure@src/lib.rs:15:59: 17:10]` will meet its required lifetime bounds

error[E0310]: the parameter type `F` may not live long enough
  --> src/lib.rs:15:50
   |
10 |       fn consume<R, F>(self, len: usize, f: F) -> Result<R,()>
   |                     - help: consider adding an explicit lifetime bound...: `F: 'static`
...
15 |           let result = (self.on_virtual_tun_write)(Box::new(|b: &mut [u8]| {
   |  __________________________________________________^
16 | |             r = f(b);
17 | |         }), len);
   | |__________^ ...so that the type `[closure@src/lib.rs:15:59: 17:10]` will meet its required lifetime bounds

error: aborting due to 3 previous errors

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

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

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=a610b15f48c8217274a75a4d03c76380

Let me begin by this error:

so that the reference type `&mut std::result::Result<R, ()>` does not outlive the data it points at

Why a reference? f returns std::result::Result<R, ()>, not a reference. So I don't see why it treats it like a mutable reference.

Also, as I can crearly see, r lives more than the Box and the closure inside the Box

The reference type error is due to the closure referencing r.

You're passing the closure in a Box which owns it. There's nothing stopping whatever type on_virtual_tun_write is from keeping a copy of it... and that includes the reference to r. I.e. you don't actually know how long the Box (and thus the closure inside of it) lives for.

If you don't need the ownership for some reason, you could pass &dyn FnOnce instead.

1 Like

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.