Conflicting lifetimes inside closure

Viewed 200

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();
}

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

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

0 Answers
Related