Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error with confusing message when deriving for struct referring to associated type #1503

Closed
rsaarelm opened this issue Mar 20, 2019 · 3 comments

Comments

@rsaarelm
Copy link

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.

@dtolnay
Copy link
Member

dtolnay commented Mar 20, 2019

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: rust-lang/rust#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>,
}

@rsaarelm
Copy link
Author

This works, thanks. Closing the issue since the error bug is compiler-side.

@0xForerunner
Copy link

I ran into this as well! This post was exactly what I was looking for. Is there any way to detect when this has happened and emit some sort of hint? Something like "consider using #[serde(bound(...))". It was non obvious to me at first what the solutions would be as I wasn't aware bound even existed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants