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, Mutex};
pub trait DecodedPacket<'a>: Send {}
pub type OnConsume = Arc<dyn for<'a> Fn(&'a mut Option<Box<dyn 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 mut decoded_packet: Option<Box<dyn DecodedPacket<'_>>> = None;
let packet = (self.on_consume)(&mut decoded_packet);
//Render packet somehow here
}
}
fn main() {
let decoder: Box<dyn Decoder + Sync> = Box::new(DummyDecoder{});
let renderer_on_consume: OnConsume =
Arc::new(move |p: &mut Option<Box<dyn DecodedPacket>>| {
let decoded_packet: Arc<Mutex<Option<Box<dyn DecodedPacket>>>> =
Arc::new(Mutex::new(None));
let on_packet = Arc::new(move |packet: Box<dyn DecodedPacket>|{
decoded_packet.lock().unwrap().replace(packet);
});
decoder.receive_ref(on_packet);
if let Some(packet) = *decoded_packet.lock().unwrap() {
p.replace(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[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/main.rs:35:58
|
35 | let decoded_packet: Arc<Mutex<Option<Box<dyn DecodedPacket>>>> =
| ^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 34:18...
--> src/main.rs:34:18
|
34 | Arc::new(move |p: &mut Option<Box<dyn DecodedPacket>>| {
| __________________^
35 | | let decoded_packet: Arc<Mutex<Option<Box<dyn DecodedPacket>>>> =
36 | | Arc::new(Mutex::new(None));
37 | | let on_packet = Arc::new(move |packet: Box<dyn DecodedPacket>|{
... |
43 | | }
44 | | });
| |_________^
note: ...but the lifetime must also be valid for the anonymous lifetime #1 defined on the body at 37:38...
--> src/main.rs:37:38
|
37 | let on_packet = Arc::new(move |packet: Box<dyn DecodedPacket>|{
| ______________________________________^
38 | | decoded_packet.lock().unwrap().replace(packet);
39 | | });
| |_____________^
note: ...so that the types are compatible
--> src/main.rs:42:27
|
42 | p.replace(packet);
| ^^^^^^
= note: expected `dyn DecodedPacket<'_>`
found `dyn DecodedPacket<'_>`
ps: I don't like the let decoded_packet: Arc<Mutex<Option<Box<dyn DecodedPacket>>>> = Arc::new(Mutex::new(None)); but I had to do it otherwise decoded_packet was getting borrowed by the closure and thus forcing the closure lifetime to be 'static