[swift-evolution] Protocol conformance error

Saagar Jha saagar at saagarjha.com
Wed Jan 17 13:53:11 CST 2018


Interestingly, it seems like Swift allows for contravariance for subclassing, in that this is valid code:

protocol A {}
protocol B: A {}

class C { // Notice this is a class, not a protocol
   func test(x: B) {}
}

class M: C {
   func test(x: A) {}
}

Is it an oversight that this doesn’t apply to protocols?

Saagar Jha

> On Jan 17, 2018, at 11:38, Paul Cantrell <cantrell at pobox.com> wrote:
> 
> Note that it would be sound for the language to allow the opposite, which is called “contravariance” (the more specific type takes a more general input):
> 
>     protocol A {}
>     protocol B: A {}
> 
>     protocol C {
>        func test(x: B)    // was A
>     }
> 
>     class M: C {
>        func test(x: A) {} // was B
>     }
> 
> It could also allow covariant return types (the more specific type returns a more specific output):
> 
>     protocol C {
>        func test() -> A
>     }
> 
>     class M: C {
>        func test() -> B {
>           fatalError("just a stub")
>        }
>     }
> 
> Some languages support this, and Swift certainly could — though I don’t know that it’s a frequently request feature.
> 
> It would also be interesting if associated type constraints allowed this, which I don’t think they currently do:
> 
>     protocol C {
>        associatedtype TestInput where B: TestInput   // error here
> 
>        func test(x: TestInput)
>     }
> 
> Curiously, the following does not work, although it seems like it should:
> 
>     protocol A {}
>     protocol B: A {}
> 
>     protocol C {
>        associatedtype TestOutput: A
> 
>        func test() -> TestOutput
>     }
> 
>     class M: C {
>        func test() -> B {
>           fatalError("just a stub")
>        }
>     }
> 
> It gives the error “inferred type 'B' (by matching requirement 'test()') is invalid: does not conform to ‘A’” even though B does conform to A. Huh.
> 
> Cheers, P
> 
> 
>> On Jan 17, 2018, at 2:43 AM, Saagar Jha via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> If we have:
>> 
>> class N: A {}
>> 
>> you can pass an N into C’s test(x:), since N is an A, but not M’s test(x:), since N is not a B. Thus, it’s not a valid conformance.
>> 
>> Saagar Jha
>> 
>>> On Jan 17, 2018, at 00:04, Roshan via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>> 
>>> Hi,
>>> 
>>> Cross posting from swift-users in case this behaviour isn't part of
>>> the language and might be interesting to you folks.
>>> 
>>> Here is some sample code that gives a protocol conformance error in a
>>> playground:
>>> 
>>> protocol A {}
>>> protocol B: A {}
>>> 
>>> protocol C {
>>>    func test(x: A)
>>> }
>>> 
>>> class M: C {
>>>    func test(x: B) {}
>>> }
>>> 
>>> Is there a reason why the compiler doesn't infer that ((B) -> ())
>>> matches ((A) -> ()) because of inheritance?
>>> 
>>> -- 
>>> Warm regards
>>> Roshan
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20180117/2c848755/attachment.html>


More information about the swift-evolution mailing list