简体   繁体   English

Rust,serde 反序列化和更高等级的特征界限 <`a>

[英]Rust, serde Deserialize and Higher Rank Trait Bounds For<`a>

I am trying to have a deeper understanding of how rust works.我试图更深入地了解 rust 的工作原理。 I am trying to do some serializing and deserializing to save and load a struct with a generic type.我正在尝试进行一些序列化和反序列化以保存和加载具有泛型类型的结构。 I got it to work, but I don't understand the HRTB and why they made the code work.我让它工作了,但我不明白 HRTB 以及他们为什么让代码工作。 Initially I have this最初我有这个

use serde::Deserialize;
use bincode;
use std::fs;

#[derive(Deserialize)]
pub struct Construct<T> {
    data: Vec<T>
}

impl <'a, T: Deserialize<'a>> Construct<T> {
    pub fn load() -> Self {
        match fs::read("data.sav") {
            Ok(d) => {
                let c: Construct<T>  = bincode::deserialize(&d).unwrap();
                c
            },
            Err(e) => {
                println!("{e}, passing empty Construct");
                Self { data: Vec::new() }
            }
        }
    }
}

whihc produces this error whihc 产生这个错误

error[E0597]: `d` does not live long enough
  --> src/main.rs:14:49
   |
10 | impl <'a, T: Deserialize<'a>> Construct<T> {
   |       -- lifetime `'a` defined here
...
14 |                 let c: Construct<T>  = bincode::deserialize(&d).unwrap();
   |                                        ---------------------^^-
   |                                        |                    |
   |                                        |                    borrowed value does not live long enough
   |                                        argument requires that `d` is borrowed for `'a`
15 |                 c
16 |             },
   |             - `d` dropped here while still borrowed

I have fixed the impl block to take a higher ranked trait bound.我已经修复了 impl 块以采用更高等级的特征界限。 And it works just fine.它工作得很好。

...
impl <T: for<'a> Deserialize<'a>> Construct<T> {
    pub fn load() -> Self {

...

As I understand it Deserialize needs to make sure that the input reference lives as long as the out structure( https://serde.rs/lifetimes.html ), and the difference between declaring the trait in the first example and using for<'a>.据我了解,反序列化需要确保输入引用与输出结构( https://serde.rs/lifetimes.html )一样长,以及在第一个示例中声明特征和使用 for<'一个>。 Is that the 1st example the lifetime is being provided by the caller and the for<'a> is getting the lifetime from the impl itself.这是生命周期由调用者提供的第一个例子,而 for<'a> 从 impl 本身获取生命周期。 ( How does "for<>" syntax differ from a regular lifetime bound? ) Am I right in thinking that with the for<'a> syntax we are getting the lifetime from the implementation block and that gives us a longer lifetime than from calling the function? “for<>”语法与常规生命周期界限有何不同? )我是否正确地认为使用 for<'a> 语法我们从实现块中获取生命周期,这给了我们比调用更长的生命周期function? Is there another way to code this load function without using HRTBs?是否有另一种方法可以在不使用 HRTB 的情况下对负载 function 进行编码?

Am I right in thinking that with the for<'a> syntax we are getting the lifetime from the implementation block我认为使用 for<'a> 语法我们从实现块中获取生命周期是否正确?

Yes, from the call bincode::deserialize(&d) .是的,来自调用bincode::deserialize(&d) Specifically, the lifetime of d .具体来说, d的生命周期。

and that gives us a longer lifetime than from calling the function这给了我们比调用 function 更长的生命周期

Nope, a shorter: instead of a caller-decided lifetime, that will always be longer than d 's lifetime (because it is declared inside our function), we get a lifetime for only d .不,一个更短的:而不是调用者决定的生命周期,它总是比d的生命周期长(因为它是在我们的函数内部声明的),我们只得到d的生命周期。

Is there another way to code this load function without using HRTBs?是否有另一种方法可以在不使用 HRTB 的情况下对负载 function 进行编码?

Yes, by bounding T to DeserializeOwned .是的,通过将T绑定到DeserializeOwned But this just hides the HRTB: DeserializeOwned uses them behind the scene.但这只是隐藏了 HRTB: DeserializeOwned在幕后使用它们。

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

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