Allow protocol conformance by declaring a method with a supertype argument

Continuing the topic Why the usage of base protocol in conformance to the protocol type is not allowed?
Currently, Swift requires an exact match of the method confirming the protocol with a protocol method declaration.
My proposition is to allow the conformation to the protocol by providing a method that takes a type or any of its supertypes as an argument:

protocol Base {
    func a()
}
protocol Sub : Base {
    func a()
}
protocol P {
    func p(_: Sub)
}
class A : P {
    func p(_: Base) {
        
    }
}

So this and an example in the previous topic should work.

It doesn’t, actually.

This is another example where the too-convenient spelling for existential types has come into play. An existential type (or a protocol type, as it’s sometimes referred to in Swift) is a “box” that can store any value of dynamic type that conforms to the corresponding protocol (or composition of protocols). You don’t need an existential type here, and using generic constraints works just fine:

protocol Base { }
protocol Sub: Base { }
protocol P {
    func p<T: Sub>(_: T)
}
class A: P {
    func p<T: Base>(_: T) { }
}

You are correct in identifying that parameters of existential type have certain limitations in terms of fulfilling protocol requirements. I haven’t fully thought through whether these limitations are due to design or implementation choices or inherent to the nature of existential types.* It is certainly true that there are some subtyping relationships which Swift could allow when fulfilling protocol requirements which currently it does not (for example, if a method is required to have return type T?, a conforming implementation today cannot have return type T—this has been discussed on this list before). Nonetheless, it is not the case that protocol requirements cannot be fulfilled by implementations that accept a wider range of inputs as arguments than is required by the protocol.

* Note that existential types in Swift (with some exceptions not relevant here) don’t conform to protocols, not even the corresponding protocol. That is, the type Base doesn’t conform to the protocol Base. This is not an entirely arbitrary design decision but actually inevitable in the general case—see the educational note on existential types for explanation.

4 Likes

Okay, the solution is clear in this case, but it has some disadvantages. For example, it is not compatible with @objc attribute.
I understand that there're some limitations on existentials, but not this exact limitation.