0

I'm trying to understand why calling a generic function with an instance of a protocol results in a compile error. Given the following code:

public protocol MyProtocol {}
public class MyClass: MyProtocol {}

public func myFunc<T: MyProtocol>(_ foo: T) -> T {
    return foo
}

public func test() {
    let foo: MyClass = MyClass()
    let bar: MyProtocol = foo

    myFunc(foo)  // ok
    myFunc(bar)  // compile error
}

The compiler fails thusly: cannot invoke 'myFunc' with an argument list of type '(MyProtocol)' on the myFunc(bar) statement.

Declaring MyProtocol as @objc allows the example to compile (presumably because it's causing MyProtocol to become some sort of concrete type behind the scenes, or something?).

Why is this disallowed in Swift, and is there a nicer workaround than @objc-ifying my protocols?

Tim Conkling
  • 121
  • 3
  • As long as `MyProtocol` has no associated type or self constraints, you could use `func myFunc(_ foo: MyProtocol) -> MyProtocol` but that would return the protocol type and not the concrete type, which may be not desired. – Palle Sep 07 '17 at 19:38
  • Ha, never knew that `@objc` allowed a protocol to conform to itself; that's cool. Adding `static` requirements or associated types to `MyProtocol` will, as expected, then prevent it from doing so (this is exactly how I hope Swift protocols will be treated in a future version of the language). Presumably the knowledge of `@objc` allows the compiler to vastly simplify the emitted code for `myFunc`, as it knows it's only dealing with Obj-C objects (so no PWTs or VWTs needed). Regardless, the core problem here, as matt says, is still that in general protocols don't conform to themselves. – Hamish Sep 07 '17 at 20:06
  • @Hamish Is it cool or is it some kind of edge-case bug? – matt Sep 07 '17 at 20:09
  • @matt I can't (immediately) see how it could be misused (as the case of adding static requirements, initialisers and associated types to the protocol *looks like* it has been handled, as it once again causes OP's code not to compile); so I'm going to go with "cool feature that I hope will be rolled out to Swift protocols in the future". – Hamish Sep 07 '17 at 20:11
  • Given OP's main question is "Why is this disallowed in Swift"; I'd say this is a dupe of https://stackoverflow.com/questions/33112559/protocol-doesnt-conform-to-itself (I'll try and update [my answer there](https://stackoverflow.com/a/43408193/2976878) with a bit on `@objc` protocols when I have some more time). – Hamish Sep 07 '17 at 20:27
  • 1
    @Hamish I've put in a query on bugs.swift.org: https://bugs.swift.org/browse/SR-55?focusedCommentId=28440&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-28440 – matt Sep 07 '17 at 20:33
  • @matt Thanks! It'll certainly be interesting to see what the response is. – Hamish Sep 07 '17 at 20:34
  • @Hamish You were right. :( – matt Sep 07 '17 at 20:56
  • Thanks for the help! Re: this being a duplicate of https://stackoverflow.com/questions/33112559/protocol-doesnt-conform-to-itself -- this makes sense now that I understand that "protocol doesn't conform to itself" is the cause of this compile error. But the error emitted by the compiler didn't make that clear to me at all. – Tim Conkling Sep 08 '17 at 20:33

0 Answers0