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

2017-12-15 Thread Kevin Nattinger via swift-evolution
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 
>  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  > 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  > wrote:
> 
>> 
>> 
>> On Fri, Dec 15, 2017 at 6:41 PM Howard Lovatt > > 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 > > wrote:
>> 
>>> 
>>> 
>>> On Fri, Dec 15, 2017 at 11:39 AM Howard Lovatt via swift-evolution 
>>> > 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 
>>> > > 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 
>>> >> > 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 

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

2017-12-15 Thread Tony Allevato via swift-evolution
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.



On Fri, Dec 15, 2017 at 9:53 PM Howard Lovatt 
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  wrote:
>
>
>
> On Fri, Dec 15, 2017 at 6:41 PM Howard Lovatt 
> 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 
>> wrote:
>>
>>
>>
>> On Fri, Dec 15, 2017 at 11:39 AM Howard Lovatt via swift-evolution <
>> 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> 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> 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
>>> >> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> > 

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

2017-12-15 Thread Tony Allevato via swift-evolution
On Fri, Dec 15, 2017 at 6:41 PM Howard Lovatt 
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  wrote:
>
>
>
> On Fri, Dec 15, 2017 at 11:39 AM Howard Lovatt via swift-evolution <
> 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> 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> 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
>> >> 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
>>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-15 Thread Howard Lovatt via swift-evolution
In Java they have simple to use var arg library functions that equate and hash 
values. I have written similar in my own code. Something like:

func equate(_ e0: (T0, T0), _ e1: (T1, T1)) -> Bool where T0: 
Equatable, T1: Equatable {
return e0.0 == e0.1 && e1.0 == e1.1
}

Unfortunately in Swift I don’t think a var arg version is possible and the 
library would have to have versions up to some arity, say 7.

But it would mitigate the pain of manually writing hash and equate for the 
cases when the compiler written version isn’t available.

-- Howard.

> On 16 Dec 2017, at 8:11 am, Dave DeLong via swift-evolution 
>  wrote:
> 
> @regexident has a long-standing proposal about how to do hashing better that 
> would address this: 
> 
> https://gist.github.com/regexident/1b8e84974da2243e5199e760508d2d25
> 
> Dave
> 
>> On Dec 15, 2017, at 2:04 PM, T.J. Usiyan via swift-evolution 
>>  wrote:
>> 
>> Can we provide a 'standard' method/function that can be used to combine 
>> ordered hash values (`[Int] -> Int`)? That could make manually implementing 
>> `hashValue` less burdensome.
>> 
>> TJ
>> 
>>> On Fri, Dec 15, 2017 at 12:08 PM, Tony Allevato via swift-evolution 
>>>  wrote:
>>> 
>>> 
 On Fri, Dec 15, 2017 at 11:39 AM Howard Lovatt via swift-evolution 
  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 
 >  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 
 >>  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
 >> 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
>>> 
>>> ___
>>> 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
> 
> 

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

2017-12-15 Thread Howard Lovatt via swift-evolution
I think that is an advanced use, rather than a common use. I would prefer that 
to be something you manually code. 

-- Howard.

> On 16 Dec 2017, at 7:08 am, Tony Allevato  wrote:
> 
> 
> 
>> On Fri, Dec 15, 2017 at 11:39 AM Howard Lovatt via swift-evolution 
>>  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 
>> >  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 
>> >>  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
>> >> 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
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-15 Thread Benjamin G via swift-evolution
On Fri, Dec 15, 2017 at 6:58 PM, Joe Groff via swift-evolution <
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?
>

I would agree with the other people saying automatic implementation of
Hashable should be all-or-nothing, but this makes me wonder : shouldn't
this "all-or-nothign" rule be the same for all the automatically
implemented protocol ? If no, then how would you know, just by looking at
the protocol, which function is "overridable" and which isn't ? I suppose
trying and having the compiler raise an error shouldn't be the only option.



>
> -Joe
> ___
> 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


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

2017-12-15 Thread Dave DeLong via swift-evolution
@regexident has a long-standing proposal about how to do hashing better that 
would address this: 

https://gist.github.com/regexident/1b8e84974da2243e5199e760508d2d25 


Dave

> On Dec 15, 2017, at 2:04 PM, T.J. Usiyan via swift-evolution 
>  wrote:
> 
> Can we provide a 'standard' method/function that can be used to combine 
> ordered hash values (`[Int] -> Int`)? That could make manually implementing 
> `hashValue` less burdensome.
> 
> TJ
> 
> On Fri, Dec 15, 2017 at 12:08 PM, Tony Allevato via swift-evolution 
> > wrote:
> 
> 
> On Fri, Dec 15, 2017 at 11:39 AM Howard Lovatt via swift-evolution 
> > 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 
> > > 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 
> >> > 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 
> >> 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 
> 
> 
> ___
> 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

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-15 Thread T.J. Usiyan via swift-evolution
Can we provide a 'standard' method/function that can be used to combine
ordered hash values (`[Int] -> Int`)? That could make manually implementing
`hashValue` less burdensome.

TJ

On Fri, Dec 15, 2017 at 12:08 PM, Tony Allevato via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> On Fri, Dec 15, 2017 at 11:39 AM Howard Lovatt via swift-evolution <
> 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> 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> 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
>> >> 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
>>
>
> ___
> 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


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

2017-12-15 Thread Tony Allevato via swift-evolution
On Fri, Dec 15, 2017 at 11:39 AM Howard Lovatt via swift-evolution <
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> 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> 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
> >> 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
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-15 Thread Matthew Johnson via swift-evolution
+1.  I think there is a reasonable general principle at work here: the 
semantics of the implementation of a refining protocol depend upon the 
semantics of the implementation of a refined protocol.  For this reason the 
compiler should not synthesize an implementation for a refining protocol unless 
it also synthesizes (and can therefore reason about) the implementation of the 
refined protocol.

> On Dec 15, 2017, at 11:58 AM, Joe Groff via swift-evolution 
>  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
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-15 Thread Joe Groff via swift-evolution


> On Dec 15, 2017, at 11:39 AM, Howard Lovatt via swift-evolution 
>  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. 

That would certainly be a simple rule. However, I think that it's more likely 
that someone might write their own hashValue in a way that's compatible with 
the default-derived equality semantics, so providing only explicit hashValue 
feels less problematic to me than providing explicit == and forgetting 
hashValue.

-Joe

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-15 Thread Howard Lovatt via swift-evolution
+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. 

> On 16 Dec 2017, at 6:24 am, Daniel Duan via swift-evolution 
>  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 
>>  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
>> 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


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

2017-12-15 Thread Daniel Duan via swift-evolution
+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 
>  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
> https://lists.swift.org/mailman/listinfo/swift-evolution
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-15 Thread Joe Groff via swift-evolution


> On Dec 15, 2017, at 10:08 AM, Wallacy  wrote:
> 
> Is possible to make the compile check what is used inside of == and then 
> provide the hash value? And if compile cannot check (for whatever reason) 
> what’s properties is used inside == then raise a compile error?

That kind of analysis would be brittle and error-prone. As Tony noted, it might 
be interesting at some point to have a more declarative means of describing 
what properties get used to synthesize structural operations on a type, which 
might allow you to override the default behavior in one place and still get 
consistent synthesized operations in terms of a different set of properties. 
That would be a whole new feature, though, that would take longer to discuss 
and design.

-Joe

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-15 Thread Tony Allevato via swift-evolution
+1, that sounds like a reasonable way to handle that situation.

This is another one of those pitfalls that could be mitigated with
something like the "transient" attribute that was discussed in earlier
discussion threads, but that's really about a slightly different problem
statement—it would let users avoid defining an explicit implementation
entirely by giving them finer control of what gets used in synthesis. But
even if we had that capability (and the time to design and implement it),
cases would still exist where someone needs to provide an explicit ==, and
the nature of those situations implies a *high probability* that the
synthesized hashValue will be inconsistent. This is a nice lower-cost way
of taking away a possible foot-gun.


On Fri, Dec 15, 2017 at 9:58 AM Joe Groff  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
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-15 Thread Wallacy via swift-evolution
Is possible to make the compile check what is used inside of == and then
provide the hash value? And if compile cannot check (for whatever reason)
what’s properties is used inside == then raise a compile error?
Em sex, 15 de dez de 2017 às 15:58, Joe Groff via swift-evolution <
swift-evolution@swift.org> escreveu:

> 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
> 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] Refining SE-0185: Should providing a custom == suppress the default hashValue?

2017-12-15 Thread Joe Groff via swift-evolution
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
https://lists.swift.org/mailman/listinfo/swift-evolution