On the other hand, explicit impls are relatively easy to read, easy to skip, and don't complicate the type definition. Everyone want to dump attributes on type definition. Skip, serde, default, derive_more
, it's easy to turn the concise definition into a soup of attributes which merge, overlap and interact in confusing ways.
It would be great if there was a better story to derives than "just add more attributes". For example, what if derive invocations were separate items, something like
struct Foo {
bar: Bar,
baz: Baz,
quux: Vec<Quux>,
moo: Arc<Mutex<Moo>>,
tump: Vec<Tump>,
}
derive!(Debug for Foo; bar, #[uppercase] baz, tump);
derive!(Hash for Foo; #[skip] baz);
This way each derive would be fully self-contained and independent, and wouldn't complicate the type definition.
Alternatively, we could write it as
#[derive(Debug(bar, #[uppercase] baz, tump))]
#[derive(Hash(#[skip] baz))]
struct Foo {
bar: Bar,
baz: Baz,
quux: Vec<Quux>,
moo: Arc<Mutex<Moo>>,
tump: Vec<Tump>,
}
That would at least have the benefit of reducing the number of attributes on fields to the minimum.