首页 > 解决方案 > 为简单结构实现克隆的生命周期要求冲突

问题描述

我正在设计一个简单的类型来保存一个Vec<u8>或一个切片(mut 或 not mut)。我在生命周期限制方面遇到问题,这次我不知道为什么会有冲突的要求:

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

操场

错误:

  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<'_>`

我只是EncodedPacket用相同的内部事物重新创建,我不明白为什么会有冲突的生命周期要求。

标签: rust

解决方案


您不能克隆可变引用。这样做的一种方法是将其包装在Rcand中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)
    }
}

操场


推荐阅读