【问题标题】:Constraining generic parameter of Rust struct to be Deserialize将 Rust 结构的泛型参数约束为反序列化
【发布时间】:2020-01-10 18:17:45
【问题描述】:

我想限制一个(反)可序列化的结构,使其具有一个也可反序列化的通用参数。派生宏 Deserialize 不需要我添加此约束,这很好,但我希望集成代码即使从未尝试反序列化库中定义的结构,也会出现编译错误。

use failure::Fallible; // 0.1.6
use serde::{Deserialize, Serialize}; // 1.0.104
use serde_json::to_string_pretty; // 1.0.44

#[derive(Deserialize, Serialize)]
struct X<T>
where
    // T: Serialize,
{
    a: u8,
    t: T,
}

type Main<'a> = &'a dyn Fn() -> Fallible<()>;

fn main() -> Fallible<()> {
    let x = X { a: 1, t: false };
    println!("{}", to_string_pretty(&x)?);

    let y: X<bool> = serde_json::from_str(r#"{"a":2,"t":true}"#)?;
    println!("{}", y.t);

    let _z: X<Main> = X { a: 3, t: &main };
    // println!("{}", to_string_pretty(&z)?);

    //let w: X<Main> = serde_json::from_str(r#"{"a":4,"t":NONONO}"#)?;

    Ok(())
}

playground

  • 如果我取消注释带有to_string_pretty(&amp;z) 的行,编译会失败,这很好。
  • 即使没有该行,如果我取消注释 where T: Serialize,编译也会在 let _z = ... 行上失败。这很棒,因为它可以帮助库集成商在实际开始序列化之前就发现他们正在使用带有不可序列化类型参数的 struct X

我尝试将where for&lt;'a&gt; T: serde::de::Deserialize&lt;'a&gt; 作为约束添加到struct X&lt;T&gt;,但即使没有使用X 的任何内容也会破坏构建

use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize)]
struct X<T>
where
    for<'a> T: serde::de::Deserialize<'a>,
{
    a: u8,
    t: T,
}

playground

有没有办法表达我正在寻找的这个约束?

【问题讨论】:

  • 您能否发布您想要工作的确切代码,并添加您收到的错误消息?我不确定您要取消注释哪些行。
  • 好的。试图澄清对库代码的无效尝试。
  • 这有帮助,谢谢!不幸的是,我仍然和你一样迷惑......
  • 第 1 段代码证明您可以在 Main 不反序列化的情况下实例化 X
    。除非您实际反序列化 X
    否则不会出错

标签: generics rust serde


【解决方案1】:

您需要使用 #[serde(bound)] 来防止 Serde 尝试自动确定 DeserializeSerialize 实现的边界:

use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize)]
#[serde(bound = "T: Serialize, for<'de2> T: Deserialize<'de2>")]
struct X<T>
where
    T: Serialize,
    for<'de2> T: Deserialize<'de2>,
{
    t: T,
}

struct NotSerializable;

fn main() {
    X { t: true };

    // X { t: NotSerializable }; // Generates compiler error
}

另见:

【讨论】:

  • 哇。谢谢。 This github discussion 和 serde 的作者 dtolnay 也有助于理解为什么它会这样工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-16
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多