我无法使用以下代码(游乐场: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);
}
我有一组可序列化的结构(InnerStructA、InnerStructA),它们都实现了一个特征。一些函数在统一它们的特征 (InnerStruct) 中是通用的。其中一些函数要求它们是可序列化和可反序列化的,因此我在特征定义中添加了 Deserialize 和 Serialize supertraits。反序列化需要添加一个命名的生命周期。
我现在想要一个 OuterStruct,它是一个通用容器,可以容纳任何类型的内部结构。如果我不应用任何特征界限,它工作正常,但是当我尝试应用特征界限时,说这个结构只对 T 有效,因为 InnerStruct 一切都会中断。编译器消息谈论生命周期,但没有一个建议有效。
一个具体的例子:对于
struct OuterStruct<T: InnerStruct> {
编译器建议
help: consider introducing a named lifetime parameter
|
23 | struct OuterStruct<'a, T: InnerStruct<'a>> {
但是这样做会导致另一个错误
error[E0392]: parameter `'a` is never used
--> src/main.rs:23:20
|
23 | struct OuterStruct<'a, T: InnerStruct<'a>> {
| ^^ unused parameter
我做错了什么?
编辑:DeserializeOwned 如果将特征更改为 DeserializedOwned,那么生命周期问题就会消失,但问题仍然存在。它似乎与将 derive(Deserialize) 应用于 OuterStruct 有关,该 OuterStruct 已经包含已应用 derive(Deserialize) 的内容。错误信息是:
note: multiple `impl`s or `where` clauses satisfying `T: Deserialize<'_>` found
在结构或枚举上放置任何不必要的界限通常是一个好主意not。这样更灵活,尤其是在处理具有生命周期参数的特征时。
所以我会尝试这样的事情:
#[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());
}
在您的示例程序中,这也将起作用:
trait InnerStruct: DeserializeOwned + Serialize {}
...
#[derive(Serialize, Deserialize)]
struct OuterStruct<T: InnerStruct> {
c: f64,
#[serde(bound(deserialize = ""))]
inner: T,
}
您的原始代码无法正常工作,因为您对结构有限制;并且
#[derive(Deserialize)]
宏正在将绑定复制到其 impl<'a> Deserialize<'a> for
结构上,而且还添加了一个 T: Deserialize<'a>
绑定。通常 T:
界限是必要的,但在这种情况下,我猜 Rust 不喜欢看到 T: Deserialize
以两种不同的方式被要求。所以解决方案是告诉宏不要在 T
. 上发出它通常的界限
serde(bound)
属性记录在here.