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
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to