> On Dec 28, 2015, at 11:19 AM, Developer <[email protected]> wrote:
> 
> My understanding of Self is that it is a special generic parameter resolved 
> by the type system to the type of the implementing structure.  That 
> resolution must be invariant because the implementing structure (here, 
> non-final classes) can choose to yank the protocol's invariants out from 
> under you when it is subclassed.  Sure, retroactively, you can make things 
> conform, but you also can't completely guarantee type safety with any kind of 
> variance in Self in all cases. 
> 
> On the other hand, using the protocol itself in either position says that you 
> only wish to restrict yourself to the protocol itself, not some specific 
> implementation.  You are necessarily specifying an upper bound (here C) on 
> the amount of "information" you can get out of the type, so it is possible to 
> introduce variance because you will never violate the protocol's invariants 
> by returning a subtype with a legal conformance.
> 
> Self doesn't mean two different things, your protocol declarations do!

My mind must be a little bit foggy this morning.  This works:

extension C: Q {
    func bar() -> Self { return self }
}

What doesn’t work, regardless of whether C is final or not, is this:

extension C: Q {
    // Cannot convert return expression of type ‘C’ to return type ‘Self'
    func bar() -> Self { return C() }
}

In order for classes to meet a protocol requirement with Self in the return 
position you must specify Self (rather than the conforming type) as the return 
type for the method.  Self in the return position of a method is treated as 
covariant.

In order for classes to meet a protocol requirement with Self in parameter 
position you must specify the type of the conforming class (you cannot specify 
Self in an argument position).  Obviously the type of the conforming class is 
invariant.

This is the sense in which Self in protocol declarations is inconsistent.  The 
requirements on conforming types are different - invariance for Self parameters 
and covariance for Self return types.

IMO it would be much more clear if this distinction was explicit rather than 
implicit based on the location of Self.  It would also be extremely useful in 
some cases to be able to specify an invariant `ConformingSelf` return type.


> 
> ~Robert Widmann
> 
> 2015/12/28 11:49、Matthew Johnson via swift-evolution 
> <[email protected] <mailto:[email protected]>> のメッセージ:
> 
>> I have brought up the idea of a non-covarying Self a few times.  
>> 
>> I was surprised to realize that Self is actually non-covarying when used for 
>> parameters in protocol declarations!
>> 
>> Here is an example demonstrating this:
>> 
>> protocol P {
>>    func foo(s: Self)
>> }
>> protocol Q {
>>    func bar() -> Self
>> }
>> 
>> class C: P {
>>    // this works!  Self as an argument type in the protocol declaration does 
>> not covary
>>    func foo(c: C) {}
>> }
>> 
>> class D: C {}
>> 
>> extension C: Q {
>>    // method ‘bar()’ in non-final class ‘C’ must return ‘Self’ to conform to 
>> protocol ‘Q'
>>    func bar() -> C { return self } 
>> }
>> 
>> 
>> It doesn’t make sense to allow a co-varying Self for parameters so I can 
>> understand how the current state might have arisen.  At the same time, using 
>> Self to mean two different things is inconsistent, confusing and it doesn’t 
>> allow us to specify a non-covarying Self as a return type in protocol 
>> requirements.  
>> 
>> As I have pointed out before, the ability to specify a non-covarying Self as 
>> a return type would make it possible to design a protocol that can be 
>> retroactively conformed to by non-final classes (such as those in Apple’s 
>> frameworks).
>> 
>> I think it would be a very good idea to introduce a non-covarying Self which 
>> would specify the type that adds conformance to the protocol and require 
>> this Self to be used in places where covariance is not possible, such as 
>> parameter types.  It would also be allowed elsewhere, such as return types, 
>> making it easier to conform non-final classes when covariance is not 
>> required by the protocol.
>> 
>> One possible name is `ConformingSelf`.  One thing I like about this name is 
>> that it makes it very clear that it is the type that introduces protocol 
>> conformance.
>> 
>> I’m interested in hearing thoughts on this.
>> 
>> Matthew
>> _______________________________________________
>> 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