Lifetime problems

Sorry for the vague title, nothing more specific comes to my mind at the moment.

I have this piece of code that does not compile:

    impl<'a, T> Decoder for NetlinkCodec<NetlinkBuffer<T>>
        where T: From<&'a [u8]> + AsRef<[u8]>
        type Item = NetlinkBuffer<T>;
        type Error = Error;
        fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
            let len = match NetlinkBuffer::new_checked(src.as_ref()) {
                Ok(buf) => buf.length() as usize,
                Err(Error::Truncated) => return Ok(None),
                Err(e) => panic!("Unknown error while reading packet: {}", e),
            let bytes = src.split_to(len);
            // create a T from a slice of bytes.
            let t = T::from(&bytes);
            // `bytes` is still borrowed here :(
            // I understand _why_ but I mean to express the fact that T::from uses the reference and
            // then does not need it anymore.

This fails with:

  --> rtnetlink/src/
44 |         let t = T::from(&bytes);
   |                          ^^^^^ borrowed value does not live long enough
49 |     }
   |     - borrowed value only lives until here
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 29:6...
  --> rtnetlink/src/
29 | impl<'a, T> Decoder for NetlinkCodec<NetlinkBuffer<T>>
   |      ^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0597`.
error: Could not compile `rtnetlink`.

I do understand the problem, because if T looks like this, it makes sense to not allow it:

    pub struct T<'a>(&'a[u8]);
    impl<'a> From<&'a [u8]> for T<'a> {
        fn from(slice: &'a [u8]) -> Self {

But what I want to allow is this kind of implementation for T:

    pub struct T(Vec<u8>);
    impl<'a> From<&'a [u8]> for T {
        fn from(slice: &'a [u8]) -> Self {

How can I express the fact that T's lifetime should not be bound the slice lifetime it’s coming from?

FWIW here is the full code:

Try T: for<'b> From<&'b [u8]> + AsRef<[u8]> instead. This way your &bytes can be an unspecified short-lived lifetime. Right now you’re forcing it to be essentially &'a bytes, which would have to outlive the function call.

1 Like

This way your &bytes can be an unspecified short-lived lifetime.

Thanks this is exactly what I wanted to express!

But… what the hell is this for<'b> syntax? I don’t remember ever seeing that.
I checked the nomicon and the rust book before posting here, and it’s not there as far as I can tell.

I don’t know if it’s in the normal book, but it’s called HRTB in the nomicon:

I always refer people to this stackoverflow answer for a good explanation of HRTB.