wigy
wigy

Reputation: 2222

Constraining generic parameter of Rust struct to be Deserialize

I would like to limit a (de)serializable struct to have a generic parameter that is also deserializable. The derive macro Deserialize does not require me to add this constraint, which is nice, but I would like the integration code to get compilation errors even if they never try to deserialize the struct defined in the library.

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

I have tried to add where for<'a> T: serde::de::Deserialize<'a> as a constraint to struct X<T>, but that breaks the build even without anything using X

use serde::{Deserialize, Serialize};

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

playground

Is there a way to phrase this constraint I am looking for?

Upvotes: 4

Views: 1242

Answers (1)

Shepmaster
Shepmaster

Reputation: 431489

You need to use #[serde(bound)] to prevent Serde from attempting to automatically determine the bounds on the Deserialize and Serialize implementations:

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
}

See also:

Upvotes: 9

Related Questions