Working around orphan rule for libraries providing trait

I wonder what use this has for libraries such as serde. For example, it has always been a huge pain, when you stick #[derive(Deserialize, Serialize)] to a struct you wrote, only to find out that a field's type Type0 is external and does not implement them.

If serde were to use the trick linked above (please see the repo) and provide something like Serialize<D>, for example, one could define struct Dummy; and implement Serialize<Dummy> for Type0. Then, some other trick would need to be used so the Serialize derive macro would use the Serialize<Dummy> implementation instead of the default one.

pub struct Dummy;

// This would cause `Type0` to implement `Serialize<Dummy>`.
impl SerializeExternal<Dummy> for Wrapper<Type0, Dummy> {
    // …
}

// And then, we can do something like this:
#[derive(Serialize)]
struct MyStruct {
    #[serde(external_dummy = "Dummy")]
    field: Type0,
    // …
}

Anyway, just some ideas here. I don't know the most useful application this workaround enables.

I'd say this SerializeExternal approach is somewhat comparable to the SerializeAs trait from serde-with.

Just checked it out, SerializeAs is interesting. And, the idea in the derive part is similar.

However, SerializeAs is quite a different approach than the workaround above:

  • Implementing SerializeAs does not make the external type implement Serialize. Instead, it enables your type to implement Serialize more easily.
  • SerializeAs mostly targets container types. I did not find an example where it allows implementing the trait for external non-container types.

I thought, the SerializeExternal approach you laid out also featured a trait distinct from the default plain Serialize.

They do call out some remote type use case e.g. here. Though for simple cases, without need for the composability of the SerializeAs trait system, the straightforward solutions of serde’s own remote deriving and #[serde(with = …)] system should be sufficient.

Some of the existing implementors, e.g. DisplayFromStr, also feature very generic implementations that are usable for external (non-container) types.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.