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.
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
Why a reference?
The closure is capturing r
by reference; you could avoid it by using the move
keyword. However, you want it to be a reference since you still want to use it afterwards.
A big constraint causing your problems stems from the fact that trait objects are 'static
by default. This is specifically a problem since the boxed closure you want to pass to on_virtual_tun_write
has references (which are not 'static
), which is why you get the errors you see.
You can fix this by making the inner trait generic over any lifetime.
pub type OnVirtualTunWrite = Arc<dyn for<'a> Fn(Box<dyn FnOnce(&mut [u8]) + 'a>, usize) -> Result<(), ()> + Send + Sync>;
// ^^^^^^^ ^^^^
Fixing this problem exposes others though:
error[E0594]: cannot assign to `r`, as it is not declared as mutable
--> src/lib.rs:16:13
|
14 | let r: Result<R,()>;
| - help: consider changing this to be mutable: `mut r`
15 | let result = (self.on_virtual_tun_write)(Box::new(|b: &mut [u8]| {
16 | r = f(b);
| ^ cannot assign
error[E0381]: borrow of possibly-uninitialized variable: `r`
--> src/lib.rs:15:59
|
15 | let result = (self.on_virtual_tun_write)(Box::new(|b: &mut [u8]| {
| ^^^^^^^^^^^^^^ use of possibly-uninitialized `r`
16 | r = f(b);
| - borrow occurs due to use in closure
You cannot capture a potentially uninitialized value in a closure. A common way to fix this is to use Option
:
let mut r: Option<Result<R,()>> = None;
let result = (self.on_virtual_tun_write)(Box::new(|b: &mut [u8]| {
r = Some(f(b));
}), len);
r.unwrap()
This also covers the potential problem that on_virtual_tun_write
may not even call the given function needed to initialize r
. As I've presented, it would panic in that case, but handling that issue would be up to you.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.