> On May 5, 2017, at 1:33 PM, Tony Allevato <[email protected]> wrote:
> 
> 
> 
> On Fri, May 5, 2017 at 11:07 AM Matthew Johnson <[email protected] 
> <mailto:[email protected]>> wrote:
>> On May 5, 2017, at 10:45 AM, Tony Allevato via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> 
>> Thanks for your feedback, everybody!
> 
> Thanks for continuing to drive this forward!
> 
>> 
>> I've updated the gist 
>> <https://gist.github.com/allevato/2fd10290bfa84accfbe977d8ac07daad> to 
>> reflect what seems to be a consensus here:
>> 
>> * Derived conformances are now opt-in (this makes the recursive case *much* 
>> cleaner, and the complexity involved in that section has been completely 
>> removed)
> 
> Can the opt-in conformance be declared in an extension?  If so, can the 
> extension be in a different module than the original declaration?  If so, do 
> you intend any restrictions, such as requiring all members of the type 
> declared in a different module to be public?  My initial thought is that this 
> should be possible as long as all members are visible.
> 
> Declaring the conformance in an extension in the same module should 
> definitely be allowed; I believe this would currently be the only way to 
> support conditional conformances (such as the `Optional: Hashable where 
> Wrapped: Hashable` example in the updated draft), without requiring deeper 
> syntactic changes.
> 
> I'm less sure about conformances being added in other modules, but I'm 
> inclined to agree with your assessment. I could see two ways of interpreting 
> it:
> 
> * E/H can only be derived in an extension in an external module if all the 
> members are accessible (and the other conditions are met).
> * E/H can be derived in an extension in an external module using only the 
> subset of accessible members (if the other conditions are met).
> 
> These are subtly different. The argument for the first would be "if you want 
> to add E/H to a type in a different module, you must *consciously* decide 
> which members you want to use in those computations". The argument for the 
> second would be "you can already make a type in a different module conform to 
> E/H and you'd be restricted to the accessible members there, so let's make 
> that path easier for users too."
> 
> The first case is probably the safer choice. I'm not sure about the 
> implementation difficulty of each.
> 
> 
>> * Classes are supported now as well
>> 
>> Please take a look at the updated version and let me know if there are any 
>> concerns! If folks like it, I'll prepare a pull request.
> 
> Will the synthesis for classes dispatch through a non-final method which is 
> expected to be overridden by subclasses?  You don’t explicitly state this but 
> it seems implied.  If so, what if  the subclass requires a custom 
> implementation?  This would require the signature of the non-final method to 
> be part of the synthesis contract.
> 
> Supporting non-final classes introduces enough complexity (especially when 
> multiple modules are involved).  I would hate to see it get sidetracked in 
> discussions regarding non-final classes and miss the Swift 4 window because 
> of that.  Given the limited time left for Swift 4 it might be better to keep 
> the initial proposal simpler and consider a followup in the Swift 5 timeframe 
> to build on the initial proposal.
> 
> For ==, the operator must already be "class final" or "static" regardless of 
> this proposal, and it can't be "overridden" as such in subclasses because the 
> arguments would be different (lhs and rhs would be the subclass, not the 
> superclass). So the compiler should be able to generate the correct 
> implementation for subclasses in all cases, right?

This won’t work because Equatable has a `Self` requirement so the `==` defined 
by the initial conforming class would be called.  In order to support non-final 
classes you would need to have that dispatch through something like an 
`isEqual` method which *can* be overridden.

> 
> For hashValue, I think the possibilities are:
> 
> * Sub is a subclass of Super. Super conforms to Hashable and implements 
> non-final hashValue. The compiler can derive it for Sub and call 
> super.hashValue in its implementation.

Yes, this makes sense.  The primary difficulty with Hashable is that it refines 
Equatable.  Refining a non-final implementation of `hashValue` is relatively 
straightforward.

> * Sub is a subclass of Super. Super conforms to Hashable and implements a 
> final hashValue. The compiler cannot derive one for Super and would silently 
> not do so.

Do you mean “the compiler cannot derive one for Sub”?

> * Sub is a subclass of Super. Super does not conform to Hashable, but Sub 
> asks to derive it. This can either (1) not be allowed, telling the user that 
> they need to write it manually in this case, or (2) be allowed and use all 
> accessible members to compute the hashValue (including those from the 
> superclass).
> 
> What do Encodable/Decodable do in these situations? It seems similar 
> solutions there would apply here.

That’s a good question.  I don’t recall whether this was addressed explicitly 
or not.

> 
> But after writing this all out, I'm inclined to agree that I'd rather see 
> structs/enums make it into Swift 4 even if it meant pushing classes to Swift 
> 4+x.

That is reasonable.  

On the other hand, I think you could come up with straightforward semantics for 
synthesizing conformance for final classes as well.  Final classes with no 
superclass should be straightforward.  Final classes that do have a superclass 
would be similarly straightforward if we decide to allow this as described in 
option (2) above regarding hashValue.  

I’m on the fence on this - if we can include final classes using option (2) 
without jeopardizing getting this in for Swift 4 I would support that.  If it’s 
going to put support for value types in Swift 4 at risk then I would not.

> 
>  
> 
>> 
>> 
>> On Fri, May 5, 2017 at 8:16 AM Nevin Brackett-Rozinsky via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> On Fri, May 5, 2017 at 1:47 AM, Xiaodi Wu via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> On Fri, May 5, 2017 at 12:41 AM, Brent Royal-Gordon <[email protected] 
>> <mailto:[email protected]>> wrote:
>> I would think only final classes could participate in this, since a 
>> subclassable class would need to allow subclasses to override equality, and 
>> you can't override a static `==` operator method.
>> 
>> I work so rarely with classes that I'm embarrassed to have to ask this 
>> question: can classes not satisfy Equatable with a `public class func ==`?
>> 
>> Currently:
>> 
>> class C: Equatable {
>>     class func == (lhs: C, rhs: C) -> Bool {
>>         return lhs === rhs
>>     }
>> }
>> 
>> Yields an error, “Operator '==' declared in non-final class 'C' must be 
>> 'final'”.
>> 
>> Nevin
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to