I’m skeptical that your use case is common enough to justify leaving open the glaring bug magnet that started this thread. Could you give an example of a common occurrence where it would be a significant improvement to explicitly write a *less precise* hash function that’s only “good enough” and still want the more precise full equality?
TBH, I think contributors here are often too quick to demand padding the walls to protect the most incompetent of engineers from themselves, but I feel like the root proposal here is a good idea. > On Dec 15, 2017, at 9:59 PM, Tony Allevato via swift-evolution > <swift-evolution@swift.org> wrote: > > Those are valid concerns for hashing algorithms in general, but there's no > connection between that and a statement that an explicitly implemented > hashValue should also require an explicitly implemented ==. Requiring that > certainly doesn't make it less likely that people will run into the problem > you've described if they implement their own hashValue—if they implement it > poorly, it just means that the could also shoot themselves in the foot by > then being forced to also implement == and possibly doing it poorly. IMO, it’s far easier to implement hashValue poorly, so I think reminding the dev they need to think about `==` too is more helpful than not. I’m not often in favor of the padded cell, but I would even consider a proposal to emit a warning if fields read in `==` is a strict subset of fields read in `hashValue`. > > > > On Fri, Dec 15, 2017 at 9:53 PM Howard Lovatt <howard.lov...@gmail.com > <mailto:howard.lov...@gmail.com>> wrote: > I would say it is an advanced use because it is an optimisation and in > addition an optimisation that requires a lot of knowledge of the fields to be > certain that a reduced hash is going to be good enough. > > The optimisation doesn’t have a great history, for example in Java they used > to hash only the 1st 6 characters of a string. However this was exploited in > denial of service attacks that generated a vast number of strings with the > same hash value, i.e same 1st 6 characters, that then overwhelmed the > dictionary (map in Java) used in the web server software to store logins. > > So it wouldn’t be something I would encourage people to do or even worse do > by accident. > > > -- Howard. > > On 16 Dec 2017, at 3:36 pm, Tony Allevato <tony.allev...@gmail.com > <mailto:tony.allev...@gmail.com>> wrote: > >> >> >> On Fri, Dec 15, 2017 at 6:41 PM Howard Lovatt <howard.lov...@gmail.com >> <mailto:howard.lov...@gmail.com>> wrote: >> I think that is an advanced use, rather than a common use. I would prefer >> that to be something you manually code. >> >> But why? Why should implementing a subset of fields for hashValue require a >> developer to also manually implement == when the default synthesized version >> would be perfectly fine? The relationship between Equatable and Hashable >> does not go both ways. >> >> In fact, requiring that they do so is *more* error prone because now they're >> being forced to implement something that the compiler would have otherwise >> generated for them. >> >> >> >> >> -- Howard. >> >> On 16 Dec 2017, at 7:08 am, Tony Allevato <tony.allev...@gmail.com >> <mailto:tony.allev...@gmail.com>> wrote: >> >>> >>> >>> On Fri, Dec 15, 2017 at 11:39 AM Howard Lovatt via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@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@swift.org <mailto:swift-evolution@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@swift.org <mailto:swift-evolution@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@swift.org <mailto:swift-evolution@swift.org> >>> >> https://lists.swift.org/mailman/listinfo/swift-evolution >>> >> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>> > _______________________________________________ >>> > swift-evolution mailing list >>> > swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>> > https://lists.swift.org/mailman/listinfo/swift-evolution >>> > <https://lists.swift.org/mailman/listinfo/swift-evolution> >>> _______________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> <https://lists.swift.org/mailman/listinfo/swift-evolution> > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution