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 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.