[swift-evolution] Universal Equatability, Hashability, and Comparability

Brent Royal-Gordon brent at architechies.com
Tue Mar 8 19:12:43 CST 2016

> - Function types in Swift do not provide a ready equality operation. We could provide a default implementation that always returns 'false', perhaps.

I think this sort of puts the lie to the idea.

We can always provide *a* definition of equality, but I suspect it will often be an *incorrect* definition. That's why you had to suggest functions should always be false: you cannot (without more effort than you want to spend) provide a correct definition of equality for it.

I mean, imagine what happens if you make functions Equatable and Hashable but with definitions that don't actually work. Currently, `Set<Void -> Void>` gives you an error:

	error: type 'Void -> Void' does not conform to protocol 'Hashable'

But with this feature in place, Swift would happily produce a Set of functions which collides endlessly, doesn't do any uniquing, never says it contains any value you pass into it, and can only remove elements by index. A type that is "never equal" completely breaks Set in practice, and there's no way for the type system to catch the problem.

If we automatically synthesize a == operator for every type, many of those operators will be incorrect. For instance, anything that includes a cache will be incorrect. Anything that includes a pointer to a buffer and ought to evaluate the buffer's contents will be incorrect. Anything that includes a closure will be incorrect. Individually, each of these cases is minor, but they multiply and interact with each other until, together, they undermine confidence in ==.

If you explicitly mark things as Equatable, then it is clear that the equality operator on them really does have a sensible definition. But if you can pass anything into ==, you will never know what will actually *work*. If everything's Equatable, then nothing is.

* * *

Auto-deriving is a different story, though, especially if it's opt-in (you have to say `deriving Equatable`). There, you presumably have looked at the default semantics and determined they're appropriate for your type.

But I think it's clear that derived conformances should eventually be a user-accessible feature. We already derive RawRepresentable and ErrorType on enums. (We also derive initializers on some types, but that's arguably a separate feature.) I think it's clear that Swift ∞ ought to allow you to derive protocol conformances; it's just a matter of scheduling.

So I think that what we ought to do is this:

• Make a best guess at what Swift ∞ would want you to do to invoke the user-specified derivation logic for an arbitrary protocol—implicit derivation or something marked by a keyword.
• Think about whether derived conformances of Equatable, Hashable, and/or Comparable are urgent enough that we should implement them before the general feature.
• If so, design these features along the lines of what we would expect the eventual user-specified derivation feature to use.

Brent Royal-Gordon

More information about the swift-evolution mailing list