> On May 13, 2016, at 9:22 AM, Matthew Johnson <[email protected]> wrote:
> 
> 
> 
> Sent from my iPad
> 
>> On May 13, 2016, at 11:08 AM, Joe Groff <[email protected]> wrote:
>> 
>> 
>>> On May 13, 2016, at 9:06 AM, Matthew Johnson <[email protected]> wrote:
>>> 
>>> 
>>>>> On May 13, 2016, at 10:39 AM, Joe Groff <[email protected]> wrote:
>>>>> 
>>>>> 
>>>>> On May 13, 2016, at 8:18 AM, Matthew Johnson <[email protected]> 
>>>>> wrote:
>>>>> 
>>>>> 
>>>>> 
>>>>> Sent from my iPad
>>>>> 
>>>>>> On May 12, 2016, at 9:21 PM, Joe Groff <[email protected]> wrote:
>>>>>> 
>>>>>> 
>>>>>>> On May 12, 2016, at 5:49 PM, Matthew Johnson via swift-evolution 
>>>>>>> <[email protected]> wrote:
>>>>>>> 
>>>>>>> The invariant StaticSelf identifier will always refer to A, unlike 
>>>>>>> Self, which is covarying and refers to
>>>>>>> the type of the actual instance. Since multiple inheritance for 
>>>>>>> non-protocol types is disallowed,
>>>>>>> this establishes this invariant type identifier with no possibility for 
>>>>>>> conflict.
>>>>>>> 
>>>>>>> Consider the following example, under the current system:
>>>>>>> 
>>>>>>> protocol StringCreatable 
>>>>>>> {
>>>>>>> 
>>>>>>> static func createWithString(s: String) -> Self
>>>>>>> 
>>>>>>> }
>>>>>>> 
>>>>>>> 
>>>>>>> extension NSURL: StringCreatable 
>>>>>>> {
>>>>>>> 
>>>>>>> // cannot conform because NSURL is non-final
>>>>>>> 
>>>>>>> 
>>>>>>> // error: method 'createWithString' in non-final class 'NSURL' must 
>>>>>>> return `Self` to conform to protocol 'A'
>>>>>>> 
>>>>>>> }
>>>>>>> 
>>>>>>> Introducing a static, invariant version of Self permits the desired 
>>>>>>> conformance:
>>>>>>> 
>>>>>>> protocol StringCreatable 
>>>>>>> {
>>>>>>> 
>>>>>>> static func createWithString(s: String) -> StaticSelf
>>>>>>> 
>>>>>>> }
>>>>>>> 
>>>>>>> 
>>>>>>> extension NSURL: StringCreatable 
>>>>>>> {
>>>>>>> 
>>>>>>> // can now conform conform because NSURL is fixed and matches the static
>>>>>>> 
>>>>>>> 
>>>>>>> // type of the conforming construct. Subclasses need not re-implement
>>>>>>> 
>>>>>>> 
>>>>>>> // NOTE: the return type can be declared as StaticSelf *or* as NSURL
>>>>>>> 
>>>>>>> 
>>>>>>> //       they are interchangeable
>>>>>>> 
>>>>>>> 
>>>>>>> static func createWithString(s: String) -> StaticSelf
>>>>>>> { 
>>>>>>> 
>>>>>>> // ...
>>>>>>> 
>>>>>>> }
>>>>>>> }
>>>>>> 
>>>>>> As I've noted before, I don't think this makes sense to encode in the 
>>>>>> protocol. `Self` is already effectively invariant within a protocol.
>>>>> 
>>>>> 'Self' is not invariant when used as a return type so I'm not sure what 
>>>>> you mean.
>>>> 
>>>> That's a property of a conformance. Class conformances are inherited, so 
>>>> they have to satisfy a protocol's requirements . Within the protocol 
>>>> definition, or in a protocol extension, `Self` is a generic parameter 
>>>> bound to a specific conforming type. When you conform a base class to a 
>>>> type, that means `Self == Base` and `Self == Derived` must be possible, 
>>>> but `Self` is never simultaneously `Base` and `Derived`.
>>>> 
>>>>>> If a protocol doesn't have the foresight to use StaticSelf, then you 
>>>>>> still have the same problems retroactively conforming class hierarchies 
>>>>>> to the protocol.
>>>>> 
>>>>> True, but in many use cases we are in control of the protocol.  This has 
>>>>> always been the case when I have personally encountered this problem.
>>>> 
>>>> That will likely change once resilient Swift frameworks start to exist. 
>>>> Changing `Self` to `StaticSelf` or back would also be a nonresilient 
>>>> change, so if frameworks get this wrong, they wouldn't be able to fix it 
>>>> without breaking ABI, which makes this even more problematic.
>>> 
>>> You can say this about many things.  It seems less problematic than having 
>>> no way to express this.  Frameworks would not be required to use it if the 
>>> authors have concerns about ABI.
>> 
>> In this particular case, making conformances non-inheritable, under the 
>> conformer's control, would avoid the issue of the framework having to 
>> anticipate its users' needs.
> 
> How would that work for class clusters?  I may have an instance of a subclass 
> but only know about the visible superclass.  When the visible superclass 
> conforms to a protocol I expect that the instance I have a reference to also 
> conforms, regardless of its dynamic type.  

In most cases, the subtype conversion should still kick in, so that we can 
convert ImplSubclass to VisibleSuperclass and invoke a generic with T == 
VisibleSuperclass instead of with T == ImplSubclass. There might be problems if 
the ImplSubclass appeared structurally in an invariant position, where implicit 
conversion is rare, but for situations where you want invariant protocol 
conformances, such as class clusters, it's rare to work to specific 
implementation classes directly, since the visible superclass is the primary 
API interface.

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

Reply via email to