Owned data is getting a lifetime

On the code below, I'm trying to transform a reference to owned data. The method to_owned ensures a 'static lifetime for the new returned type. However, it's complaining that this returned type is not really 'static because of the impl <'a>. I don't see what does 'a have to do with this since all the returned objects in to_owned are owned and thus should be 'static.

pub enum RRtspEncodedPacket<'a> {
    Owned(Data<Body>),
    Ref(&'a Data<Body>)
}

pub struct Body(Inner);

enum Inner {
    Vec(Vec<u8>),
    Custom(Box<dyn Custom>),
}

trait Custom: AsRef<[u8]> + Send + Sync + 'static {}

pub struct Data<Body> {
    pub(crate) channel_id: u8,
    pub(crate) body: Body,
}

pub trait EncodedPacket<'a, T: Send>: Send {
    fn to_owned(&self) -> Box<dyn EncodedPacket<'static, T>>;
}

impl<'a> EncodedPacket<'a, u8> for RRtspEncodedPacket<'a> {
    fn to_owned(&self) -> Box<dyn EncodedPacket<'static, u8>> {
        match self {
            Self::Owned(o) => Box::new(Self::Owned(*o.clone())),
            Self::Ref(data) => Box::new(Self::Owned(*(*data).clone()))
        }
    }
}

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

Error:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
  --> src/lib.rs:27:40
   |
27 |             Self::Owned(o) => Box::new(Self::Owned(*o.clone())),
   |                                        ^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 24:6...
  --> src/lib.rs:24:6
   |
24 | impl<'a> EncodedPacket<'a, u8> for RRtspEncodedPacket<'a> {
   |      ^^
note: ...so that the types are compatible
  --> src/lib.rs:27:40
   |
27 |             Self::Owned(o) => Box::new(Self::Owned(*o.clone())),
   |                                        ^^^^^^^^^^^
   = note: expected `RRtspEncodedPacket<'_>`
              found `RRtspEncodedPacket<'a>`
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the expression is assignable
  --> src/lib.rs:27:31
   |
27 |             Self::Owned(o) => Box::new(Self::Owned(*o.clone())),
   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: expected `Box<(dyn EncodedPacket<'static, u8> + 'static)>`
              found `Box<dyn EncodedPacket<'static, u8>>`

Self is RRtspEncodedPacket<'a> not RRtspEncodedPacket<'static>

You can get farther with

impl<'a> EncodedPacket<'a, u8> for RRtspEncodedPacket<'a> {
    fn to_owned(&self) -> Box<dyn EncodedPacket<'static, u8>> {
        match self {
            Self::Owned(o) => Box::new(RRtspEncodedPacket::Owned((*o).clone())),
            Self::Ref(data) => Box::new(RRtspEncodedPacket::Owned((*data).clone()))
        }
    }
}

But you run into Data<Body> not being Clone

Your RRtspEncodedPacket is pretty much a std::borrow::Cow so you may want to try to build on Cow to leverage the methods and traits already written for it.

2 Likes

If you're ok converting Inner to a Vec on clone, you can write something like this:

impl Clone for Inner {
    fn clone(&self)->Self {
        Self::Vec(match self {
            Self::Vec(v) => v.clone(),
            Self::Custom(c) => Vec::from(<dyn Custom as AsRef<[u8]>>::as_ref(&**c))
        })
    }
}

Playground

Why does the EncodedPacket trait have a lifetime parameter?

1 Like

Use name of the type instead of Self, because Self specifically refers to the non-static version. You're changing the type from T<'not_static> to T<'static> — they are different and incompatible in this case.

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.