[swift-evolution] Refining SE-0185: Should providing a custom == suppress the default hashValue?

Tony Allevato tony.allevato at gmail.com
Fri Dec 15 14:08:31 CST 2017


On Fri, Dec 15, 2017 at 11:39 AM Howard Lovatt via swift-evolution <
swift-evolution at swift.org> wrote:

> +1
> I think the simple solution of if you provide either == or hashValue you
> have to provide both is the best approach. Good catch of this bug.
> -- Howard.
>

That would be a significant usability hit to a common use case. There are
times where a value is composed of N fields where N is large-ish, and
equality is dependent on the values of all N fields but the hash value only
needs to be "good enough" by considering some subset of those fields (to
make computing it more efficient).

That still satisfies the related relationship between == and hashValue, but
a user wanting to explicitly implement a more efficient hashValue should
*not* necessarily be required to explicitly write the same == that would be
synthesized for them in that case.



>
> > On 16 Dec 2017, at 6:24 am, Daniel Duan via swift-evolution <
> swift-evolution at swift.org> wrote:
> >
> > +1. The proposal wasn’t explicit enough to have either supported or be
> against this IMO. It’s a sensible thing to spell out.
> >
> > Daniel Duan
> > Sent from my iPhone
> >
> >> On Dec 15, 2017, at 9:58 AM, Joe Groff via swift-evolution <
> swift-evolution at swift.org> wrote:
> >>
> >> SE-0185 is awesome, and brings the long-awaited ability for the
> compiler to provide a default implementation of `==` and `hashValue` when
> you don't provide one yourself. Doug and I were talking the other day and
> thought of a potential pitfall: what should happen if you provide a manual
> implementation of `==` without also manually writing your own `hashValue`?
> It's highly likely that the default implementation of `hashValue` will be
> inconsistent with `==` and therefore invalid in a situation like this:
> >>
> >> struct Foo: Hashable {
> >> // This property is "part of the value"
> >> var involvedInEquality: Int
> >> // This property isn't; maybe it's a cache or something like that
> >> var notInvolvedInEquality: Int
> >>
> >> static func ==(a: Foo, b: Foo) -> Bool {
> >>   return a.involvedInEquality == b.involvedInEquality
> >> }
> >> }
> >>
> >> As currently implemented, the compiler will still give `Foo` the
> default hashValue implementation, which will use both of `Foo`'s properties
> to compute the hash, even though `==` only tests one. This could be
> potentially dangerous. Should we suppress the default hashValue derivation
> when an explicit == implementation is provided?
> >>
> >> -Joe
> >> _______________________________________________
> >> swift-evolution mailing list
> >> swift-evolution at swift.org
> >> https://lists.swift.org/mailman/listinfo/swift-evolution
> > _______________________________________________
> > swift-evolution mailing list
> > swift-evolution at swift.org
> > https://lists.swift.org/mailman/listinfo/swift-evolution
> _______________________________________________
> 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/20171215/a51085d6/attachment.html>


More information about the swift-evolution mailing list