简体   繁体   English

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

[英]Lifetime issue while implementing a trait for a generic type which implements a trait with an associated lifetime

I am writing a deserializer ( Vec<u8> (Raw JSON) to any type T) for a project and trying to use serde for it.我正在为一个项目编写一个反序列化器( Vec<u8> (Raw JSON) 到任何类型的 T)并尝试使用 serde 。 Here's my trait which I to decode the data:这是我解码数据的特征:

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

Since I intend to use #[derive(Deserialize)] on my structs, I am writing an impl for any type that implements the Deserialize trait with an arbitrary lifetime:因为我打算在我的结构上使用#[derive(Deserialize)] ,所以我正在为任何实现具有任意生命周期的 Deserialize 特征的类型编写一个 impl:

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

But I am getting a lifetime error:但是我遇到了终身错误:

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

I understand why the compiler is mad at me.我理解为什么编译器生我的气。 Upon checking the implementation of from_slice, I figured it has an associated lifetime.在检查 from_slice 的实现后,我发现它有一个关联的生命周期。 I am sure input is an owned value, but from_slice requires a reference, so here I am returning reference of a value which gets dropped when the function ends, which is clearly incorrect.我确定 input 是一个拥有的值,但 from_slice 需要一个引用,所以在这里我返回一个值的引用,该值在 function 结束时被丢弃,这显然是不正确的。 My question is, is there a way to ensure that the value is borrowed for <'a> lifetime (ie the lifetime supplied by the caller of this function).我的问题是,有没有办法确保在 <'a> 生命周期内借用该值(即此函数的调用者提供的生命周期)。 I can't update the trait because it will cause a disaster.我无法更新特征,因为它会导致灾难。

If you want a value that doesn't borrow from the slice, you can use DeserializeOwned as the trait bound, which has no associated lifetime (and therefore only stores owned values).如果你想要一个不从切片中借用的值,你可以使用DeserializeOwned作为特征绑定,它没有关联的生命周期(因此只存储拥有的值)。 For example, this compiles:例如,这编译:

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 操场

This is equivalent to using a higher-ranked trait bound with the lower-level Deserialize trait bound:这等效于使用具有较低级别Deserialize特征界限的较高等级的特征界限:

impl<T: for<'de> Deserialize<'de>> Decode for T {
    // ...
}

The correct way to use Deserialize with a lifetime is using Higher Rank Trait Bounds : Specifically telling compiler that this lifetime is valid for all (concerned) lifetimes using the for<'a> notation.使用带生命周期的反序列化的正确方法是使用Higher Rank Trait Bounds :特别告诉编译器此生命周期对使用for<'a>表示法的所有(相关)生命周期有效。 The code will look like this:代码将如下所示:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM