[swift-evolution] [Draft] Automatically deriving Equatable and Hashable for certain value types

Brent Royal-Gordon brent at architechies.com
Tue May 31 02:03:49 CDT 2016

> I'm not a fan of AutoEquatable or AutoHashable. These protocols suggest that automatic conformance can be defined in the language itself and that derived protocol instances don't have to be implemented as compiler intrinsics. That's just not the case. You cannot define something like
> @auto protocol AutoEquatable : Equatable {
>   ...
> }
> because what would you write instead of "..."? Copy Lisp-Macros? Copy Template-Haskell? I don't really need to disagree here, I could just say "good idea, do you want to make a proposal for this?" and then I will never hear again anything from this idea, because no one will be able to write the "detailed design" section of that proposal. (at least, I don't know how to design such a feature; the solution space looks empty to me. there are similar issues with "property behaviors" IMHO, but that's another story.)

Actually, I believe you could write a version of AutoEquatable merely by adding a couple items from the generics manifesto:

	protocol AutoEquatable: Equatable {}
	func == <T: AutoEquatable> (lhs: T, rhs: T) -> Bool {
		let lhsMirror = Mirror(reflecting: lhs)
		let rhsMirror = Mirror(reflecting: rhs)
		for ((lhsLabel, lhsValue), (rhsLabel, rhsValue)) in zip(lhs.children, rhs.children) {
			guard lhsLabel == rhsLabel else { return false }
			guard let lhsValue = (lhsValue as! Equatable) openas U else { return false }
			guard let rhsValue = rhsValue as? U else { return false }
			guard lhsValue == rhsValue else { return false }
		return true

This is not the all-powerful code-generation-based solution everyone's pining for, of course. But (modulo a few bugs stemming from this being a proof of concept) it *would* work. If the compiler occasionally decides to write a more specialized equivalent, well, that's its prerogative, right?

(In a recent thread on property reflection, I discussed the possibility of attaching lists of properties to types, with property behaviors being used to add properties to the lists. That would actually work better than `Mirror` for this task, but it's a more speculative feature.)

As for an eventual compile-time-generated implementation, well, that kind of thing *does* seem to be on the design team's radar. We've already seen a concrete proposal along those lines in property behaviors; I could imagine a "type behaviors" feature being introduced in the future which could introspect a type and generate new members based on what it sees. And generalized hygienic macros keep coming up too. Just because they aren't in Swift 3 doesn't mean we can't design as though they'll be here eventually.

Brent Royal-Gordon

More information about the swift-evolution mailing list