How to use a protocol with additional class methods in a generic extension in Swift?

I am trying to extend on an existing class using a class method like:

@objc public protocol MyProtocol {
    optional class func foo() -> Int
}

      

And I use this protocol in a generic extension like:

extension MyClass {

    public func bar<T: MyProtocol>() {
        ...
        let x: Int = T.self.foo!() // if I do not use "self" or "!" here, I will have a compiler error
        ...
    }

      

This should work, but when I build it, Xcode says "Command / Applications / Xcode.app / Contents / Developer / Toolchains / XcodeDefault.xctoolchain / usr / bin / swiftc failed with exit code 1". If I don't use "optional" in the protocol, I don't need to expand foo () in the extension, and everything works well even if I remove the "me". Can anyone tell me why and how to do the extra work correctly? Thanks in advance.

+3


source to share


1 answer


It looks like you found a (rather obscure) bug in the Swift compiler causing it to crash. This reproduces everything you need in one file to make it crash swiftc

:

import Foundation
@objc protocol P { optional class func f() }
func f<T: P>(t: T) { T.self.f?() }

      

(you don't need to call f

for it to crash)

You should probably feed the radar as a compiler crash is never expected, no matter what your code is.

If you try to do it without optional

, it works (and you can even rotate self

). My guess is that the generics implementation does not currently account for the possibility of additional class-level functionality.



You can do this without generics:

func f(p: MyProtocol) {
    (p as AnyObject).dynamicType.foo?()
}

      

(maybe even a better way, but I can't seem to notice it).

You need to do this AnyObject

because if you try to call .dynamicType.foo?()

on p

, you will get “access to the members of the protocol type” “MyProtocol.Type is“ not implemented. ”I wouldn't be surprised if the generic version fails with this.

I'd also say it's worth asking yourself if you really need a protocol with additional methods (especially at the class level) and if there is a way to do what you want completely statically using generics (since you're already semi-doing).

+2


source







All Articles