创建返回实现 serde::Deserialize 的值的函数时的生命周期错误
Posted
技术标签:
【中文标题】创建返回实现 serde::Deserialize 的值的函数时的生命周期错误【英文标题】:Lifetime error when creating a function that returns a value implementing serde::Deserialize 【发布时间】:2017-09-19 03:54:31 【问题描述】:我正在使用 serde 和 serde_json 1.0 从 base64 字符串中解码数据:
fn from_base64_str<T: Deserialize>(string: &str) -> T
let slice = decode_config(string, URL_SAFE).unwrap();
serde_json::from_slice(&slice).unwrap()
当我编译时,我得到了这个:
error[E0106]: missing lifetime specifier
--> src/main.rs:6:23
|
6 | fn from_base64_str<T: Deserialize>(string: &str) -> T
| ^^^^^^^^^^^ expected lifetime parameter
查看 serde 文档,Deserialize
定义为:
pub trait Deserialize<'de>: Sized
所以我添加了生命周期:
fn from_base64_str<'de, T: Deserialize<'de>>(string: &str) -> T
let slice = decode_config(string, URL_SAFE).unwrap();
serde_json::from_slice(&slice).unwrap()
然后编译器告诉我:
error: `slice` does not live long enough
--> src/main.rs:11:29
|
11 | serde_json::from_slice(&slice).unwrap()
| ^^^^^ does not live long enough
12 |
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'de as defined on the body at 9:64...
--> src/main.rs:9:65
|
9 | fn from_base64_str<'de, T: Deserialize<'de>>(string: &str) -> T
| _________________________________________________________________^ starting here...
10 | | let slice = decode_config(string, URL_SAFE).unwrap();
11 | | serde_json::from_slice(&slice).unwrap()
12 | |
| |_^ ...ending here
我只知道 Rust 中生命周期的基本知识,所以我对 trait Deserialize
中的 'de
感到非常困惑。
如何修复此类函数中的生命周期错误?我正在使用 Rust 1.18.0-nightly (452bf0852 2017-04-19)
【问题讨论】:
【参考方案1】:我从Serde issue 891 找到了答案:我应该使用DeserializeOwned
而不是Deserialize
。
【讨论】:
【参考方案2】:This section of the Serde website covers Deserialize
bounds in detail.
有两种主要方法可以编写Deserialize
trait bound,无论是在 impl 块、函数还是其他任何地方。
<'de, T> where T: Deserialize<'de>
这意味着“T 可以从 some 生命周期中反序列化。”调用者可以决定那是什么生命周期。通常,当调用者还提供正在反序列化的数据时,例如在像 serde_json::from_str
这样的函数中,会使用此方法。在这种情况下,输入数据还必须具有生命周期'de
,例如它可以是&'de str
。
<T> where T: DeserializeOwned
这意味着“T 可以从任何生命周期中反序列化。”被调用者可以决定什么生命周期。通常这是因为要反序列化的数据将在函数返回之前被丢弃,因此不能允许 T 从中借用。例如,一个函数接受 base64 编码的数据作为输入,从 base64 解码,反序列化 T 类型的值,然后丢弃 base64 解码的结果。此绑定的另一个常见用途是从 IO 流反序列化的函数,例如 serde_json::from_reader
。
从技术上讲,DeserializeOwned
trait 等同于 higher-rank trait bound for<'de> Deserialize<'de>
。唯一的区别是DeserializeOwned
阅读起来更直观。这意味着 T 拥有所有被反序列化的数据。
【讨论】:
以上是关于创建返回实现 serde::Deserialize 的值的函数时的生命周期错误的主要内容,如果未能解决你的问题,请参考以下文章