Cor*_*one 1 traits lifetime rust serde
我无法让以下代码工作(游乐场:https://play.rust-lang.org/? version=stable&mode= debug&edition=2021&gist=4379c2006dcf3d32f59b0e44626ca667)。
use serde::{Serialize, Deserialize};
trait InnerStruct<'delife>: Deserialize<'delife> + Serialize {}
#[derive(Serialize, Deserialize)]
struct InnerStructA{
a: i32
}
impl InnerStruct<'_> for InnerStructA {}
#[derive(Serialize, Deserialize)]
struct InnerStructB{
a: i32,
b: i32
}
impl InnerStruct<'_> for InnerStructB {}
#[derive(Serialize, Deserialize)]
struct OuterStruct<T: InnerStruct>{ // Remove the word "InnerStruct" and this works
c: f64,
inner: T
}
fn print_json<T: for<'a> InnerStruct<'a>>(obj: T) {
println!("Serde JSON: {:?}", serde_json::to_string(&obj).unwrap());
}
fn main() {
let inner_a = InnerStructA{a: 123};
let inner_b = InnerStructB{a: 234, b: 567};
println!("Serde JSON: {:?}", serde_json::to_string(&inner_a).unwrap());
println!("Serde JSON: {:?}", serde_json::to_string(&inner_b).unwrap());
print_json(inner_a);
print_json(inner_b);
}
Run Code Online (Sandbox Code Playgroud)
我有一个可序列化的结构集合(InnerStructA、InnerStructA),它们都实现了一个特征。有些函数在统一它们的特征(InnerStruct)中是通用的。其中一些函数要求它们可序列化和反序列化,因此我已将 Deserialize 和 Serialize supertraits 添加到特征定义中。反序列化需要添加命名生命周期。
我现在想要一个 OuterStruct,它是一个通用容器,可以容纳任何类型的内部结构。如果我不应用任何特征边界,它就可以正常工作,但是当我尝试应用特征边界来表示该结构仅对 T 为 InnerStruct 有效时,一切都会中断。编译器消息讨论了生命周期,但所有建议都不起作用。
一个具体的例子:对于
use serde::{Serialize, Deserialize};
trait InnerStruct<'delife>: Deserialize<'delife> + Serialize {}
#[derive(Serialize, Deserialize)]
struct InnerStructA{
a: i32
}
impl InnerStruct<'_> for InnerStructA {}
#[derive(Serialize, Deserialize)]
struct InnerStructB{
a: i32,
b: i32
}
impl InnerStruct<'_> for InnerStructB {}
#[derive(Serialize, Deserialize)]
struct OuterStruct<T: InnerStruct>{ // Remove the word "InnerStruct" and this works
c: f64,
inner: T
}
fn print_json<T: for<'a> InnerStruct<'a>>(obj: T) {
println!("Serde JSON: {:?}", serde_json::to_string(&obj).unwrap());
}
fn main() {
let inner_a = InnerStructA{a: 123};
let inner_b = InnerStructB{a: 234, b: 567};
println!("Serde JSON: {:?}", serde_json::to_string(&inner_a).unwrap());
println!("Serde JSON: {:?}", serde_json::to_string(&inner_b).unwrap());
print_json(inner_a);
print_json(inner_b);
}
Run Code Online (Sandbox Code Playgroud)
编译器建议
struct OuterStruct<T: InnerStruct> {
Run Code Online (Sandbox Code Playgroud)
但这样做会导致另一个错误
help: consider introducing a named lifetime parameter
|
23 | struct OuterStruct<'a, T: InnerStruct<'a>> {
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
编辑:DeserializeOwned 如果特征更改为 DeserializedOwned,那么生命周期问题就会消失,但问题仍然存在。这似乎与将导出(反序列化)应用于 OuterStruct 有关,该 OuterStruct 已经包含已应用导出(反序列化)的内容。错误信息是:
note: multiple `impl`s or `where` clauses satisfying `T: Deserialize<'_>` found
Run Code Online (Sandbox Code Playgroud)
通常最好不要对结构或枚举设置任何不必要的界限。这样更灵活,尤其是在处理具有生命周期参数的特征时。
所以我会尝试这样的事情:
#[derive(Serialize, Deserialize)]
struct OuterStruct<T> {
c: f64,
inner: T,
}
fn print_json<'a, T>(obj: T)
where
T: InnerStruct<'a>,
{
println!("Serde JSON: {:?}", serde_json::to_string(&obj).unwrap());
}
Run Code Online (Sandbox Code Playgroud)
在您的示例程序中,这也将起作用:
trait InnerStruct: DeserializeOwned + Serialize {}
...
#[derive(Serialize, Deserialize)]
struct OuterStruct<T: InnerStruct> {
c: f64,
#[serde(bound(deserialize = ""))]
inner: T,
}
Run Code Online (Sandbox Code Playgroud)
您的原始代码无法正常工作,因为您对结构有限制;宏#[derive(Deserialize)]将绑定复制到其impl<'a> Deserialize<'a> for结构上,同时还添加了一个T: Deserialize<'a>绑定。通常这个T:界限是必要的,但在这种情况下,我猜 Rust 不喜欢T: Deserialize以两种不同的方式看到需要。因此,解决方案是告诉宏不要在 上发出其通常的界限T。
该serde(bound)属性记录在此处。
| 归档时间: |
|
| 查看次数: |
323 次 |
| 最近记录: |