The question is how you want
AnyEquatable to actually implement the
Standard library currently has two very different erasing wrappers over types that conform to
Equatable (or an inherited protocol): one being
AnyHashable, as you mention, but there's also
AnyIndex, which abstracts
There is a good reason to have
AnyHashable as is, because it is able to work "standalone": a hashable value can produce its hash regardless of its
Self constraint, and here the fact that
Hashable inherits from
Equatable is a more semantical constraint than anything inherently required for hashing to work. If you would try to compare two
AnyHashables with different underlying types, it will gracefully return
On the other hand,
AnyIndex is an abstraction to be able to work with collections regardless of their index types, but indices can't really do anything as "standalone" values: they are tied to
endIndex of a collection, for example, and such still need to be able to compare as their underlying types. Because of this, comparing two unrelated
AnyIndexes is a semantic disaster, so it will actually crash at runtime if you'd try to.
So the question is, how should
AnyEquatable actually behave when trying to equate two underlying values? On the one hand, it seems reasonable that
AnyEquatable(5) == AnyEquatable("5") should return
false — that is, you just assume that diffrent types are incomparable — but should
AnyEquatable(5 as Int) == AnyEquatable(5 as Int8) return false? Or should these crash?
More generally, I beleive there already have been some discussions on enabling the compiler to sythesize
Any<Whatever> wrappers over protocols with
Self and stuff, so it might be a much more generic question of whether protocols should be granted this ability and what their default runtime behaviour should be.