> On Dec 28, 2015, at 12:04 PM, Developer <devteam.cod...@gmail.com> wrote:
> 
> That doesn't look like a variance issue to me, that's about the same 
> "information" invariant I talked about before.  The former works because self 
> resolves to an invariant type, the type of the implementing structure, which 
> satisfies the requirement Self introduces.  The latter does not because Self 
> indicates a level of specificity C cannot guarantee.  Self is magic, but it 
> is also implemented as a generic parameter.  So think of it this way:
> 
> protocol Q {
>   func bar<T>() -> T { return Q() }
> }
> 
> You wouldn't expect that to compile, would you?

It actually does work for structs and for final classes because Self becomes 
invariant when used in a return type position for them.

protocol Q {
    func bar() -> Self
}

final class C: Q {
    func bar() -> C { return C() }
}


> 
> ~Robert Widmann
> 
> 2015/12/28 12:49、Matthew Johnson <matt...@anandabits.com 
> <mailto:matt...@anandabits.com>> のメッセージ:
> 
>> 
>>> On Dec 28, 2015, at 11:19 AM, Developer <devteam.cod...@gmail.com 
>>> <mailto:devteam.cod...@gmail.com>> 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 
>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> のメッセージ:
>>> 
>>>> 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
>>>> 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

Reply via email to