num::Zero exists to define the additive identity value of a type, i.e. the value y that fulfils the equation x + y == x (for all x). Without a corresponding definition of + this is a nonsensical definition, which is why the Add bound is there.
If you just want an arbitrary placeholder value, that's what Default is for.
By the same logic, if there's no correct way to add points together, there is no additive identity value for a Point and thus no possible correct implementation of Zero.
On the other hand, it feels like a lot of your trait bounds are not as semantically relevant, and are only there to support the implementation. You might be better served by writing blanket implementations instead of overridable defaults in many cases, for example:
That is very Neat, had seen this style of implementations but wasn't really sure why do it this way vs doing it straight in trait but your example makes it very clear. Thank you.
One noob question is does this enable the traits for any type which has the same generics params?
Slightly contrived example but lets says a struct table<100,10,String> get the same traits automatically?
Yes, every type that meets the conditions in the impl<T> SomeTrait for T where ... {} block has the trait implemented, even if that type is defined in another crate.
The biggest downside to this approach is that the implementation is not overridableā Every type that meets the listed requirements must use this implementation, and cannot implement a possibly-more-efficient one. Also, coherence rules sometimes make it hard to implement the traits for other types which aren't covered by the blanket implementation.