Deriving Serde's Serialize or Deserialize forces generic type to be serialisable although it does not need to be

天涯浪子 提交于 2020-08-27 06:43:54

问题


My type A, which can contain anything that implements trait Trait, is serialisable, although the type implementing the trait Trait might not be. In my case, it cannot be - it's a private asymmetric key:

extern crate serde;
#[macro_use]
extern crate serde_derive;

use serde::de::DeserializeOwned;
use serde::Serialize;

trait Trait {
    type SerialisableType: Clone + Serialize + DeserializeOwned;

    fn inner(&self) -> &Self::SerialisableType;
}

#[derive(Serialize, Deserialize)]
enum A<T: Trait> {
    Variant0(B<T>), // *** NOTE: Compiles if this is commented ***
    Variant1(T::SerialisableType),
}

#[derive(Serialize, Deserialize)]
struct B<T: Trait> {
    inner: T::SerialisableType,
}

// ==============================================

struct NonSerialisable {
    serialisable: Serialisable,
}

impl Trait for NonSerialisable {
    type SerialisableType = Serialisable;

    fn inner(&self) -> &Self::SerialisableType {
        &self.serialisable
    }
}

#[derive(Clone, Serialize, Deserialize)]
struct Serialisable(Vec<u8>);

#[derive(Serialize, Deserialize)]
enum E {
    Variant0(A<NonSerialisable>),
    Variant1(B<NonSerialisable>),
}

fn main() {}

playground

This errors out with:

error[E0277]: the trait bound `NonSerialisable: serde::Serialize` is not satisfied
  --> src/main.rs:43:10
   |
43 | #[derive(Serialize, Deserialize)]
   |          ^^^^^^^^^ the trait `serde::Serialize` is not implemented for `NonSerialisable`
   |
   = note: required because of the requirements on the impl of `serde::Serialize` for `A<NonSerialisable>`
   = note: required by `serde::Serializer::serialize_newtype_variant`

error[E0277]: the trait bound `NonSerialisable: serde::Deserialize<'_>` is not satisfied
  --> src/main.rs:43:21
   |
43 | #[derive(Serialize, Deserialize)]
   |                     ^^^^^^^^^^^ the trait `serde::Deserialize<'_>` is not implemented for `NonSerialisable`
   |
   = note: required because of the requirements on the impl of `serde::Deserialize<'_>` for `A<NonSerialisable>`
   = note: required by `serde::de::VariantAccess::newtype_variant`

If I comment out A::Variant0, as mentioned in the inline comment in the code, then it compiles fine. This makes me think that the compiler is unable to deduce that B<T> is serialisable, but then it actually is able to deduce that because it can figure out E is serialisable which would require B to be serialisable as well.

Where is the problem?


回答1:


During macro expansion the compiler has not yet determined which B is being referred to inside Variant0 or how that B may use its type parameters. As such, macro expansion infers trait bounds that would work for the most common cases of what B might be, like if B were Box or Vec. In those cases serializing B<T> would require T: Serialize and deserializing B<T> would require T: Deserialize<'de>.

You can provide handwritten generic type bounds to replace the inferred bounds.

#[derive(Serialize, Deserialize)]
#[serde(bound = "")]
enum A<T: Trait> {
    Variant0(B<T>),
    Variant1(T::SerialisableType),
}


来源:https://stackoverflow.com/questions/50047334/deriving-serdes-serialize-or-deserialize-forces-generic-type-to-be-serialisable

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!