Associated types and derive trait bounds
The problem & its context
In a lot of cases an automatically-derived trait bound is not correct. For example:
pub struct SetKeyValue<O: Identifiable> {
pub object: O::Id,
pub key: Name,
pub value: JsonString,
}
The impl iroha_schema_derive generates a has incorrect trait bounds inferred: O: Identifiable + IntoSchema, while in reality what it needs is O: Identifiable + TypeId, O::Id: IntoSchema (that is, TypeId type parameters and IntoSchema on types used in the fields).
This is also a problem for std derives and serde.
The simplistic algorithm that only involves the type parameters is used in compiler-builtin derives, as well as in a lot of ecosystem crates (like serde). It's my understanding that this is mostly done because doing it correctly was hard due to limitations in trait type-checking (https://github.com/rust-lang/rust/issues/26925, https://github.com/serde-rs/serde/issues/2463).
In both serde and iroha_schema_derive there is an escape hatch that lets you specify the trait bounds manually. For std derives, there are crates that allow you to do this (for example derive-where).
Specifying trait bounds manually is not ideal, but works well enough for hand-written types. When using macro_rules! it's basically impossible though, since it requires generating string literals and passing then to attr macros. This is currently blocking me from implementing query projections (#5063)
parity_scale_codec has an algorithm that actually looks at the fields of structures it works on, and in most cases generates more correct bounds. There are still some issues with it, but they are much more mild. As a testament to parity_scale_codec's approach robustness: we did not have to use any of the escape hatch mechanisms provided (#[codec(dumb_trait_bound)], #[codec(encode_bound)], #[codec(decode_bound)], #[codec(mel_bound)]) by them in any of the iroha code.
The (local) solution
The solution, in the context of #5063, is twofold:
- for
iroha_schema_derive, which we control, use the trait bound generation algorithm fromparity_scale_codec: #5132 - for
serde, which we don't control, and it doesn't seem likely that this issue will be remedied soon (serde-rs/serde#2784, serde-rs/serde#2463, serde-rs/serde#2736, serde-rs/serde#2727), the best solution I can come up with is to make a helper proc macro that will generate the right#[serde(bounds(...))]with a similar algorithm