为实现具有关联生命周期的特征的泛型类型实现特征时的生命周期问题

问题描述

我正在为一个项目编写一个反序列化器(Vec<u8>(原始 JSON)到任何类型 T)并尝试使用 serde。这是我解码数据的特征:

pub trait Decode: Sized {
    fn try_decode(input: Vec<u8>) -> Result<Self,InternalError>;
}

因为我打算在我的结构上使用 #[derive(Deserialize)],所以我正在为实现具有任意生命周期的 Deserialize trait 的任何类型编写一个实现:

impl<'a,T: Deserialize<'a>> Decode for T {
    fn try_decode(input: Vec<u8>) -> Result<Self,InternalError> {
        if let Ok(t) = serde_json::from_slice(&input) {
            Ok(t)
        } else {
            Err(Internal::decode("Could not decode"))
        }
    }
}

但我收到了一个终生错误

error[E0597]: `input` does not live long enough
  --> src/decode.rs:16:47
   |
14 | impl<'a,T: Deserialize<'a>> Decode for T {
   |      -- lifetime `'a` defined here
15 |     fn try_decode(input: Vec<u8>) -> Result<Self,InternalError> {
16 |         if let Ok(t) = serde_json::from_slice(&input) {
   |                        -----------------------^^^^^^-
   |                        |                      |
   |                        |                      borrowed value does not live long enough
   |                        argument requires that `input` is borrowed for `'a`
...
21 |     }
   |     - `input` dropped here while still borrowed

我理解编译器为什么生我的气。在检查 from_slice 的实现后,我认为它具有相关的生命周期。我确信输入是一个拥有的值,但是 from_slice 需要一个引用,所以在这里我返回一个值的引用,该值在函数结束时被删除,这显然是不正确的。我的问题是,有没有办法确保在 生命周期(即此函数调用者提供的生命周期)内借用该值。我无法更新特征,因为它会导致灾难。

解决方法

如果你想要一个不从切片借用的值,你可以使用 DeserializeOwned 作为 trait bound,它没有关联的生命周期(因此只存储拥有的值)。例如,这会编译:

impl<T: DeserializeOwned> Decode for T {
    fn try_decode(input: Vec<u8>) -> Result<Self,InternalError> {
        if let Ok(t) = serde_json::from_slice(&input) {
            Ok(t)
        } else {
            todo!()
        }
    }
}

Playground

,

使用具有生命周期的反序列化的正确方法是使用 Higher Rank Trait Bounds:使用 for<'a> 表示法专门告诉编译器此生命周期对所有(相关的)生命周期都有效。代码将如下所示:

impl<T: for<'de> Deserialize<'de>> InputCoercible for T {
    // ...trait methods...
}