Sometimes I want a type
T to implement some trait (e.g.
PartialEq) but prevent other types containing
T from deriving that trait.
This post is a question about how to achieve this better.
As a concrete examples, I’ll look at
Ident in the compiler, because I’ve recently noticed that careless deriving of
PartialEq for structures containing spans and identifiers created a mine field of bugs in macro expansion. Constructions that are commonly used by people are now bug-free, but step to the left or step to the right and things stop working.
Spans can be reasonably compared themselves, but usually if they are used in larger structures they serve informational purpose, e.g. one token tree should be equal to another identical token tree regardless of where it’s located in the source file.
Identifiers are a bit different - they can be reasonably compared hygienically, but before the comparison you may want to tweak some contexts or you may want to compare unhygienically in some cases. Larger structures need to decide how exactly they want to compare identifiers.
So I want a way to create a barrier for
derive(PartialEq) on structures containing
If someone tries to derive, they should see a message “STOP! THINK!” and write implementation of
PartialEq manually, or not write it at all and write something more flexible instead.
One possible solution is to capitulate and not to implement
PartialEq and add a separate comparison function instead.
Then you can use something like
Ident::equal(i1, i2) for comparisons and something like
ComparableIdent wrapper for maps/sets (
I tried this approach, it’s workable but not convenient and involves some amount of suffering.
Any better solution?
(Possibly including enhancements to