I'm trying to create a trait for a Decoder
that can return a packet that contains a reference inside. That is, I don't need to copy the packet to an owned object just so it's 'static
. Here's the sketch:
use std::sync::Arc;
pub trait DecodedPacket<'a>: Send {}
pub type OnConsume = Arc<dyn Fn() -> Option<Box<dyn for<'a> DecodedPacket<'a>>> + Send + Sync>;
pub trait Decoder: Send{
fn receive_ref(&self,on_packet: Arc<dyn for<'a> FnMut(Box<dyn DecodedPacket<'a>>)>);
}
pub struct DummyDecoder {}
impl Decoder for DummyDecoder {
fn receive_ref(&self,_: Arc<dyn for<'a> FnMut(Box<dyn DecodedPacket<'a>>)>){
unimplemented!();
}
}
struct DummyRenderer {
on_consume: OnConsume
}
impl DummyRenderer {
pub fn render(&self) {
let packet = (self.on_consume)();
//Render packet somehow here
}
}
fn main() {
let decoder: Box<dyn Decoder + Sync> = Box::new(DummyDecoder{});
let renderer_on_consume: OnConsume =
Arc::new(move || -> Option<Box<dyn DecodedPacket<'_>>> {
let decoded_packet;
let on_packet = Arc::new(|packet: Box<dyn DecodedPacket<'_>>|{
decoded_packet = Some(packet);
});
decoder.receive_ref(on_packet);
decoded_packet
});
let dummy_renderer = DummyRenderer{
on_consume: renderer_on_consume
};
dummy_renderer.render();
}
You can see that receive_ref
expects a function that can deal with all lifetimes, so it should work for a small non 'static
lifetime. However, the compiler is making all the lifetimes 'static
:
Error:
error[E0308]: mismatched types
--> src/main.rs:33:29
|
33 | Arc::new(move || -> Option<Box<dyn DecodedPacket<'_>>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected enum `Option<Box<(dyn for<'a> DecodedPacket<'a> + 'static)>>`
found enum `Option<Box<dyn DecodedPacket<'_>>>`
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:38:33
|
38 | decoder.receive_ref(on_packet);
| ^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 35:38...
--> src/main.rs:35:38
|
35 | let on_packet = Arc::new(|packet: Box<dyn DecodedPacket<'_>>|{
| ______________________________________^
36 | | decoded_packet = Some(packet);
37 | | });
| |_____________^
note: ...so that the type `[closure@src/main.rs:35:38: 37:14]` will meet its required lifetime bounds
--> src/main.rs:38:33
|
38 | decoder.receive_ref(on_packet);
| ^^^^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the expression is assignable
--> src/main.rs:38:33
|
38 | decoder.receive_ref(on_packet);
| ^^^^^^^^^
= note: expected `Arc<(dyn for<'a> FnMut(Box<(dyn DecodedPacket<'a> + 'static)>) + 'static)>`
found `Arc<dyn for<'a> FnMut(Box<(dyn DecodedPacket<'a> + 'static)>)>`
error[E0308]: mismatched types
--> src/main.rs:39:13
|
39 | decoded_packet
| ^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected enum `Option<Box<(dyn for<'a> DecodedPacket<'a> + 'static)>>`
found enum `Option<Box<dyn DecodedPacket<'_>>>`
To be fair I'm kinda confused about when to put '_
and how for<'a>
works inside an Arc
. What does it mean for an Arc
to be able to expect all lifetimes?