media-io / yaserde

Yet Another Serializer/Deserializer
MIT License
179 stars 60 forks source link

yaserde_derive YaSerialize and YaDeserialize macros get confused when a struct also has serde::Serialize and serde::Deserialize derive macros. #103

Closed ephraimkunz closed 3 years ago

ephraimkunz commented 3 years ago

This code snippet:

use yaserde_derive::{YaDeserialize, YaSerialize};
use serde::{Deserialize, Serialize};

fn main() {
    let test = A{
        b: B {
            c: "Hi".to_string()
        }
    };

    println!("{}", yaserde::ser::to_string(&test).unwrap());
}

#[derive(YaSerialize, YaDeserialize, Serialize, Deserialize)]
pub struct A {
    b: B,
}
#[derive(Serialize, Deserialize, YaSerialize, YaDeserialize, Default)]
pub struct B {
    c: String
}

fails with the following errors:

error[E0034]: multiple applicable items in scope
  --> gedcomx-cli/src/main.rs:33:10
   |
33 | #[derive(YaSerialize, YaDeserialize, Serialize, Deserialize)]
   |          ^^^^^^^^^^^ multiple `serialize` found
   |
note: candidate #1 is defined in an impl of the trait `YaSerialize` for the type `B`
  --> gedcomx-cli/src/main.rs:37:34
   |
37 | #[derive(Serialize, Deserialize, YaSerialize, YaDeserialize, Default)]
   |                                  ^^^^^^^^^^^
note: candidate #2 is defined in an impl of the trait `Serialize` for the type `B`
  --> gedcomx-cli/src/main.rs:37:10
   |
37 | #[derive(Serialize, Deserialize, YaSerialize, YaDeserialize, Default)]
   |          ^^^^^^^^^
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
help: disambiguate the associated function for candidate #1
   |
33 | #[derive(YaSerialize::serialize(&YaSerialize, YaSerialize), YaDeserialize, Serialize, Deserialize)]
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #2
   |
33 | #[derive(Serialize::serialize(&YaSerialize, YaSerialize), YaDeserialize, Serialize, Deserialize)]
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0034]: multiple applicable items in scope
  --> gedcomx-cli/src/main.rs:33:23
   |
33 | #[derive(YaSerialize, YaDeserialize, Serialize, Deserialize)]
   |                       ^^^^^^^^^^^^^ multiple `deserialize` found
   |
note: candidate #1 is defined in an impl of the trait `YaDeserialize` for the type `B`
  --> gedcomx-cli/src/main.rs:37:47
   |
37 | #[derive(Serialize, Deserialize, YaSerialize, YaDeserialize, Default)]
   |                                               ^^^^^^^^^^^^^
note: candidate #2 is defined in an impl of the trait `Deserialize` for the type `B`
  --> gedcomx-cli/src/main.rs:37:21
   |
37 | #[derive(Serialize, Deserialize, YaSerialize, YaDeserialize, Default)]
   |                     ^^^^^^^^^^^
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
help: disambiguate the associated function for candidate #1
   |
33 | #[derive(YaSerialize, YaDeserialize::deserialize, Serialize, Deserialize)]
   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
help: disambiguate the associated function for candidate #2
   |
33 | #[derive(YaSerialize, Deserialize::deserialize, Serialize, Deserialize)]
   |                       ^^^^^^^^^^^^^^^^^^^^^^^^

Basically what's happening here is that the YaSerialize and YaDeserialize derive macros are generating code that calls <something>.serialize(...) and <something>::deserialize(). But when the serde macros are there, there's functions with the same name generated by them and since Rust doesn't have function overloading it doesn't know which to call.

The solution is to specify which one by using ::yaserde::YaSerialize::serialize(item, writer) and <#struct_name as ::yaserde::YaDeserialize>::deserialize(reader) so that we are saying we want the serialize that's from the YaSerialize trait.