I recently was reading the book "Rust for Rustaceans" and found a part where it mentioned that it is generally a good idea to implement certain commonly useful traits on your types.
Even if you personally won't use one of those traits' functionality, there is a chance one of your API users will, and the Orphan Rule makes it hard for them to implement those traits on your types after the fact.
Useful traits
In this spirit, I have a list of traits I want to derive for my types (where compatible):
This means I now have a list of 10 different traits that I want to start implementing more consistently in my projects.
I could just check manually, but that could get laborious and error-prone depending on the volume of code involved. I'd much rather automate the process of checking for this stuff.
Lints
I noticed there are lints to warn me when I am passing-up on opportunities to implement these useful traits, but I've only been able to find such lints for 2 of them: Copy and Debug:
While I understand the motivation behind such a lint for Debug, and partially also for Copy, the notion of useful is very subjective. Some type may contain values, which are Eq or Ord, but for the type itself it does not make sense to implement those due to the respective domain.
So the set of useful trait implementations is highly variable across domains and applications.
I’m pretty confident that you don’t want Copy. This is consistent with Rust’s preference for a “move” instead of “copy” semantic.
Let the user be explicit about having to figure it out with a newtype pattern if need be. This makes explicit when any non-trivial memory allocation is at play.
Keep in mind Copy is a flag/signal trait that requires Clone, but otherwise the two traits are orthogonal.
I oppose this blanket assertion. It depends, whether it makes sense.
I am currently implementing a networking protocol (Zigbee), which uses u8, u16 and the likes to represent bit flags. In order to implement a proper API, I use the eponymous bitflags crate which requires a newtype wrapper for the respective struct, so I mostly end up with something like
Also note, that I didn't derive Ord* here. u8 is Ord, but ordering sets of bitflags does not make any sense in this context (though it could be useful if you want to use the flags as keys in a BTreeMap, I guess).