Serde: Error with confusing message when deriving for struct referring to associated type

Created on 20 Mar 2019  路  2Comments  路  Source: serde-rs/serde

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.

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 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>,
}

All 2 comments

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sackery picture sackery  路  3Comments

Yamakaky picture Yamakaky  路  3Comments

pitkley picture pitkley  路  3Comments

dtolnay picture dtolnay  路  4Comments

dtolnay picture dtolnay  路  3Comments