Poperton
Poperton

Reputation: 2148

conflicting lifetime requirements on implementing Clone for simple struct

I'm designing a simple type to hold either a Vec<u8> or a slice (mut or not mut). I'm having problems on lifetime constraints and this time I don't know why there are conflicting requirements:

use std::vec::Vec;

pub enum EncodedPacket<'a> {
    Owned(Vec<u8>),
    Ref(&'a [u8]),
    RefMut(&'a mut [u8])
}

impl<'a> EncodedPacket<'a> {
    pub fn new_ref(slice: &'a [u8]) -> EncodedPacket<'a> {
        EncodedPacket::Ref(slice)
    }

    pub fn new_ref_mut(slice: &'a mut [u8]) -> EncodedPacket<'a> {
        EncodedPacket::RefMut(slice)
    }

    pub fn new_owned(vec: Vec<u8>) -> EncodedPacket<'a> {
        EncodedPacket::Owned(vec)
    }
}

impl<'a> Clone for EncodedPacket<'a> {
    fn clone(&self) -> Self {
        match self {
            EncodedPacket::Owned(vec)=> EncodedPacket::new_owned(*vec),
            EncodedPacket::Ref(slice) => EncodedPacket::new_ref(*slice),
            EncodedPacket::RefMut(slice) => EncodedPacket::new_ref_mut(*slice)
        }
    }
}

Playground

Error:

  Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for pattern due to conflicting requirements
  --> src/lib.rs:28:35
   |
28 |             EncodedPacket::RefMut(slice) => EncodedPacket::new_ref_mut(*slice)
   |                                   ^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 24:14...
  --> src/lib.rs:24:14
   |
24 |     fn clone(&self) -> Self {
   |              ^^^^^
note: ...so that reference does not outlive borrowed content
  --> src/lib.rs:28:35
   |
28 |             EncodedPacket::RefMut(slice) => EncodedPacket::new_ref_mut(*slice)
   |                                   ^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 23:6...
  --> src/lib.rs:23:6
   |
23 | impl<'a> Clone for EncodedPacket<'a> {
   |      ^^
note: ...so that the expression is assignable
  --> src/lib.rs:25:9
   |
25 | /         match self {
26 | |             EncodedPacket::Owned(vec)=> EncodedPacket::new_owned(*vec),
27 | |             EncodedPacket::Ref(slice) => EncodedPacket::new_ref(*slice),
28 | |             EncodedPacket::RefMut(slice) => EncodedPacket::new_ref_mut(*slice)
29 | |         }
   | |_________^
   = note: expected `EncodedPacket<'a>`
              found `EncodedPacket<'_>`

I'm just recreating EncodedPacket with the same internal things, I don't see why there are conflicting lifetime requirements at all.

Upvotes: 1

Views: 61

Answers (1)

Netwave
Netwave

Reputation: 42708

You cannot clone a mutable reference. One way of doing this would be to wrap it in Rc and Rc<RefCell>:

use std::vec::Vec;
use std::cell::RefCell;
use std::rc::Rc;

#[derive(Clone)]
pub enum EncodedPacket<'a> {
    Owned(Vec<u8>),
    Ref(Rc<&'a [u8]>),
    RefMut(Rc<RefCell<&'a mut [u8]>>)
}

impl<'a> EncodedPacket<'a> {
    pub fn new_ref(slice: &'a [u8]) -> EncodedPacket<'a> {
        EncodedPacket::Ref(Rc::new(slice))
    }

    pub fn new_ref_mut(slice: &'a mut [u8]) -> EncodedPacket<'a> {
        EncodedPacket::RefMut(Rc::new(RefCell::new(slice)))
    }

    pub fn new_owned(vec: Vec<u8>) -> EncodedPacket<'a> {
        EncodedPacket::Owned(vec)
    }
}

Playground

Upvotes: 3

Related Questions