[swift-evolution] [Review] SE-0185 - Synthesizing Equatable and Hashable conformance

Tony Allevato tony.allevato at gmail.com
Thu Aug 10 10:19:14 CDT 2017

On Thu, Aug 10, 2017 at 3:40 AM Haravikk via swift-evolution <
swift-evolution at swift.org> wrote:

> On 10 Aug 2017, at 10:32, Martin Waitz <tali at admingilde.org> wrote:
> Hi Haravikk,
> Am 2017-08-10 11:07, schrieb Haravikk via swift-evolution:
> I don't feel that conforming to
> Equatable/Hashable is sufficient as an opt-in. Consider for example
> someone who declares their type as Equatable/Hashable, then sets to
> work on the details of their type, forgetting to implement the actual
> equatable/hashable behaviour they want.
> This is no different than a default implementation of the protocol.
> In fact, the proposal just adds something like this:
>    extension Struct<A, B, ...>: Equatable where A: Equatable, B:
> Equatable, ... {
>        static func ==(lhs: Self, rhs: Self) -> Bool { /* insert
> implementation here */ }
>    }
> We don't require/support some special keywords for other protocols with
> default implementation either,
> so I see no reason to add them here.
> Your concerns are orthogonal to this proposal and should be discussed
> independently.
> I disagree.
> This is not the same as a default protocol implementation, as a default
> implementation can only act upon properties/methods that are clearly
> defined by the protocol itself. This feature by comparison is an automatic
> implementation that by design must make assumptions about the contents of a
> concrete type.
> Consider a type that contains some kind of "volatile" data, i.e-
> properties that are not necessarily crucial to the type, and so should not
> be considered during equality. If I make a mistake and end up using the
> synthesised test for equality, then two values that should be identified as
> equal, will not be equated as such because the synthesised option cannot
> account for implementation details that it has no awareness of.

This has come up in discussion in the past, where I argued for some means
> of marking values to prevent them from being included in the synthesised
> method(s). This is covered in alternatives as "transient" values, but I
> disagree with the conclusion that this can simply be added later, as it is
> IMO crucial to the way this feature would work.

Thanks for your feedback, Haravikk!

My hunch is that structs and enums where such volatile data exists are the
exception, not the norm, when it comes to considering equality. This
proposal is very much intended to be useful syntactic sugar for the common
case while not preventing any existing behavior (providing your own
implementation) and alluding to future directions where the behavior can be
extended to other use cases.

I disagree that @transient is crucial for this feature to work—that feature
only applies to the set of types that contain volatile data, that volatile
data and all the other fields are all Equatable/Hashable, and the user
wants to synthesize Eq/Hash for a subset of its fields. I certainly agree
that such a set is non-empty, but I it's also small enough that it can be
considered at a later date.

It's important for a proposal like this to be as focused and targeted as
possible, and leave features that are not absolutely required for future
directions. For the record, I would *love* to see something like @transient
proposed after this (which is why I call it out in the proposal), but such
a feature would also affect Codable and this proposal should not mix

> Even if there were a @transient attribute or whatever from the start, I'd
> still prefer to set this within the context of having explicitly asked for
> Equatable/Hashable to be synthesised, and without such a feature it only
> makes it more crucial that the opt-in occur in a manner more explicit than
> conforming to Equatable/Hashable.
> My disagreement pretty much boils down to the fact that I do not feel that
> opting in simply by conforming is sufficient given that the desired
> behaviour is assumed; I strongly feel that a more explicit declaration of
> "I specifically want to use this automatic behaviour" is required, either
> via attribute or conforming to a more explicit protocol.

> I actually *like* the fact that conforming to Equatable requires me to
> implement ==, as it ensures that I do-so, and prefer that that behaviour
> remain, as it forces me to do something about it. Even with synthesised
> behaviour as an option, it should be exactly that, an option; i.e- when my
> conformance to Equatable fails, I can choose either to implement ==, or
> opt-in to an automatic substitute.

I sympathize with these concerns, and a great deal of thought and
discussion was done around the best way to surface this feature in the last
couple of mailing list threads about this topic. But at the time this
proposal and its implementation were written, the synthesis for Codable had
already been implemented and this proposal adopts the same synthesis
conditions that were used by Codable. Core team members expressed that the
implementation for Eq/Hash should follow those existing practices as
closely as possible; I agreed that consistency is important so that we
don't have to document intricate nuances between the implementations of
protocol synthesis.

Given that constraint, IMO it would be incorrect for this proposal to
create an inconsistent set of synthesis conditions compared to Codable, and
it is out of scope for this proposal to suggest changes to Codable. If you
feel that synthesis should be made more explicit across Equatable,
Hashable, and Codable, please do propose that!

> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170810/88e49745/attachment.html>

More information about the swift-evolution mailing list