Serde 1.0.89, rustc 1.33.0
Trying to compile the following
use serde_derive::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
pub struct CompletelyUnrelatedType(u32);
pub trait Trait: Sized {
type Dependent;
}
#[derive(Serialize, Deserialize)]
pub struct Struct<T: Trait> {
stuff: Vec<T::Dependent>
}
gives me the error message
error[E0277]: the trait bound `<T as Trait>::Dependent: _IMPL_DESERIALIZE_FOR_CompletelyUnrelatedType::_serde::Serialize` is not satisfied
--> src/lib.rs:12:5
|
12 | stuff: Vec<T::Dependent>
| ^^^^^ the trait `_IMPL_DESERIALIZE_FOR_CompletelyUnrelatedType::_serde::Serialize` is not implemented for `<T as Trait>::Dependent`
|
= help: consider adding a `where <T as Trait>::Dependent: _IMPL_DESERIALIZE_FOR_CompletelyUnrelatedType::_serde::Serialize` bound
= note: required because of the requirements on the impl of `_IMPL_DESERIALIZE_FOR_CompletelyUnrelatedType::_serde::Serialize` for `std::vec::Vec<<T as Trait>::Dependent>`
= note: required by `_IMPL_DESERIALIZE_FOR_CompletelyUnrelatedType::_serde::ser::SerializeStruct::serialize_field`
Shouldn't this just work as long as T has a T::Dependent that is serializable? At least the error message shouldn't refer to derivations from a different type.
Sorry about the confusing error! The paths in there are not up to Serde so I don't think there is anything we could do in Serde to fix them. Those errors are emitted by the compiler at some point after macro expansion. The fact that they refer to CompletelyUnrelatedType is a longstanding compiler bug: https://github.com/rust-lang/rust/issues/46991.
To make this work you will need to add a bound(...) attribute to provide the right trait bounds for the generated Serialize and Deserialize impls. By default Serde emits a bound of T: Serialize for any type parameter T that is used in a serialized field, and T: Deserialize<'de> for any type parameter used in a deserialized field. In your struct, T is never serialized or deserialized (only T::Dependent is) so we don't emit bounds. The way associated types are used is generally impossible to tell during macro expansion so we stick with a simple heuristic and provide bound(...) to fill in bounds manually when necessary.
#[derive(Serialize, Deserialize)]
#[serde(bound(
serialize = "T::Dependent: Serialize",
deserialize = "T::Dependent: Deserialize<'de>",
))]
pub struct Struct<T: Trait> {
stuff: Vec<T::Dependent>,
}
This works, thanks. Closing the issue since the error bug is compiler-side.
Most helpful comment
Sorry about the confusing error! The paths in there are not up to Serde so I don't think there is anything we could do in Serde to fix them. Those errors are emitted by the compiler at some point after macro expansion. The fact that they refer to CompletelyUnrelatedType is a longstanding compiler bug: https://github.com/rust-lang/rust/issues/46991.
To make this work you will need to add a
bound(...)attribute to provide the right trait bounds for the generated Serialize and Deserialize impls. By default Serde emits a bound ofT: Serializefor any type parameterTthat is used in a serialized field, andT: Deserialize<'de>for any type parameter used in a deserialized field. In your struct,Tis never serialized or deserialized (onlyT::Dependentis) so we don't emit bounds. The way associated types are used is generally impossible to tell during macro expansion so we stick with a simple heuristic and providebound(...)to fill in bounds manually when necessary.