更新时间:2022-10-16 17:59:16
看起来您已经在Swift编译器中发现了一个(相当模糊的)错误这会导致它崩溃。
下面是在单个文件中需要的所有副本的崩溃 swiftc
:
import Foundation
@objc protocol P {optional class func f()}
func f (t:T){T.self.f?()}
(您不需要调用 f
它会崩溃)
您应该提交一个雷达,因为无论您的代码是什么,编译器崩溃都不会发生。
如果您尝试在没有可选
的情况下执行此操作,它可以工作(甚至可以将 self
)。我的猜测是泛型的实现目前没有考虑可选的类级函数的可能性。
你可以在没有泛型的情况下这样做:
func f(p:MyProtocol){
(p为AnyObject).dynamicType.foo?()
}
(甚至可能有更好的方法,但我无法发现它)。
您需要 AnyObject
类型转换,因为如果您尝试调用 .dynamicType.foo?()
on p
直接获得访问协议类型值的成员'MyProtocol.Type'未实现。如果通用版本的崩溃与此相关,我不会感到惊讶。
我也会说它值得问自己,你是否真的需要一个协议可选的方法(特别是类级别的方法)以及是否有办法完全静态地使用泛型(因为您已经半参与)。
I am trying using extension for an existing class with class method like:
@objc public protocol MyProtocol {
optional class func foo() -> Int
}
And I am using this protocol in an extension with generic 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 do not use "optional" in the protocol, I do not need to unwrap the foo() in the extension and everything works well even if I remove the "self". Can anyone tell me why and how to make the optional work properly? Thanks in advance.
It looks like you've found a (fairly obscure) bug in the Swift compiler that's causing it to crash.
Here's a reproduction that's all you need in a single file to 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 file a radar since the compiler crashing is never expected behavior no matter what your code.
If you tried to do this without the optional
, it'll work (and you can even ditch the self
). My guess is the implementation of generics doesn't currently account for the possibility of optional class-level functions.
You can do it without generics like this:
func f(p: MyProtocol) {
(p as AnyObject).dynamicType.foo?()
}
(there may even be a better way but I can't spot it).
You need the AnyObject
cast because if you try to call .dynamicType.foo?()
on p
directly you get "accessing members of protocol type value 'MyProtocol.Type' is unimplemented". I wouldn't be surprised if the crash of the generic version is related to this.
I'd also say that its worth asking yourself whether you really need a protocol with optional methods (especially class-level ones) and whether there's a way to do what you want entirely statically using generics (as you're already semi-doing).