为什么直接引用协议方法swift编译不通过?
Why does swift not compile when referring to protocol method directly?
给定以下结构:
struct TestStruct {
func test() {
print("Something")
}
}
像这样引用 test
函数有效:
let testFunc = TestStruct.test // (TestStruct) -> () -> Void
为了执行该功能,您必须执行以下操作:
testFunc(TestStruct())() // Prints "Something"
假设你让 TestStruct
遵守一个协议:
protocol Test {
func test()
}
extension TestStruct: Test {}
现在尝试像这样通过协议引用 test
函数是行不通的:
let testFunc = Test.func // Does not compile, no error message
testFunc
的类型不应该是(Test) -> () -> Void
吗?为什么现在正在编译?
根据 SR-75,您编写的代码旨在在某些时候工作。他们还没有实施。
编译器崩溃而不是打印错误这一事实意味着您发现了编译器错误。
:; xcrun swift
Welcome to Apple Swift version 4.0 (swiftlang-900.0.54.10 clang-900.0.31). Type :help for assistance.
1> struct TestStruct {
2. func test() {
3. print("Something")
4. }
5. }
6> protocol Test {
7. func test()
8. }
9.
10. extension TestStruct: Test {}
11> let testFunc = Test.test
Segmentation fault: 11
“Segmentation fault: 11”表示编译器崩溃。 您应该去 https://bugs.swift.org/,如果您没有帐户,请创建一个帐户,然后提交错误报告。
您可以通过将测试代码放入文件并编译它来查看编译器堆栈跟踪:
:; echo 'protocol Test { func test() }; let testFunc = Test.test' > main.swift && xcrun swiftc main.swift
0 swift 0x000000010b5efeaa PrintStackTraceSignalHandler(void*) + 42
1 swift 0x000000010b5ef2e6 SignalHandler(int) + 662
2 libsystem_platform.dylib 0x00007fff9742fb3a _sigtramp + 26
3 libsystem_platform.dylib 0x00007f82e307de00 _sigtramp + 1271194336
4 swift 0x0000000108818c2c swift::Lowering::SILGenFunction::manageOpaqueValue(swift::Lowering::SILGenFunction::OpaqueValueState&, swift::SILLocation, swift::Lowering::SGFContext) + 188
5 swift 0x000000010882fa1b swift::ASTVisitor<(anonymous namespace)::RValueEmitter, swift::Lowering::RValue, void, void, void, void, void, swift::Lowering::SGFContext>::visit(swift::Expr*, swift::Lowering::SGFContext) + 11067
6 swift 0x000000010882d6a1 swift::ASTVisitor<(anonymous namespace)::RValueEmitter, swift::Lowering::RValue, void, void, void, void, void, swift::Lowering::SGFContext>::visit(swift::Expr*, swift::Lowering::SGFContext) + 1985
7 swift 0x0000000108838f01 swift::ASTVisitor<(anonymous namespace)::RValueEmitter, swift::Lowering::RValue, void, void, void, void, void, swift::Lowering::SGFContext>::visit(swift::Expr*, swift::Lowering::SGFContext) + 49185
8 swift 0x0000000108849329 void llvm::function_ref<void (swift::Expr*)>::callback_fn<swift::Lowering::RValue swift::Lowering::SILGenFunction::emitOpenExistentialExpr<swift::Lowering::RValue, (anonymous namespace)::RValueEmitter::visitOpenExistentialExpr(swift::OpenExistentialExpr*, swift::Lowering::SGFContext)::$_5>(swift::OpenExistentialExpr*, (anonymous namespace)::RValueEmitter::visitOpenExistentialExpr(swift::OpenExistentialExpr*, swift::Lowering::SGFContext)::$_5)::'lambda'(swift::Expr*)>(long, swift::Expr*) + 41
9 swift 0x00000001088499e7 swift::Lowering::SILGenFunction::emitOpenExistentialExprImpl(swift::OpenExistentialExpr*, llvm::function_ref<void (swift::Expr*)>) + 1591
10 swift 0x000000010882e1cb swift::ASTVisitor<(anonymous namespace)::RValueEmitter, swift::Lowering::RValue, void, void, void, void, void, swift::Lowering::SGFContext>::visit(swift::Expr*, swift::Lowering::SGFContext) + 4843
11 swift 0x000000010882cb74 swift::Lowering::SILGenFunction::emitExprInto(swift::Expr*, swift::Lowering::Initialization*) + 148
12 swift 0x000000010881ccf6 swift::Lowering::SILGenFunction::emitPatternBinding(swift::PatternBindingDecl*, unsigned int) + 198
13 swift 0x00000001087ce3cf swift::ASTVisitor<swift::Lowering::SILGenModule, void, void, void, void, void, void>::visit(swift::Decl*) + 559
14 swift 0x00000001087cd4ab swift::Lowering::SILGenModule::emitSourceFile(swift::SourceFile*, unsigned int) + 1115
15 swift 0x00000001087cee39 swift::SILModule::constructSIL(swift::ModuleDecl*, swift::SILOptions&, swift::FileUnit*, llvm::Optional<unsigned int>, bool) + 841
16 swift 0x0000000107f6dedc performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) + 13020
17 swift 0x0000000107f69394 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 7332
18 swift 0x0000000107f1ead8 main + 12248
19 libdyld.dylib 0x00007fff97220235 start + 1
20 libdyld.dylib 0x000000000000000f start + 1759378907
Stack dump:
0. Program arguments: /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -c -primary-file main.swift -target x86_64-apple-macosx10.9 -enable-objc-interop -sdk /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk -color-diagnostics -module-name main -o /var/folders/kn/1d839myx4tlghz34f_lh3hvc0000gn/T/main-65ce73.o
<unknown>:0: error: unable to execute command: Segmentation fault: 11
<unknown>:0: error: compile command failed due to signal 11 (use -v to see invocation)
你的结构和你的协议之间的区别是协议没有实现方法test
。它只是声明了一个名为 test
的方法。表达式 TestStruct.test
return 是对结构的方法 test
实现的引用。因为该协议没有 test
的实现,编译器无法 return 对此的引用。
注意:协议 Test
不 知道 关于其实现 类 或结构的任何信息。因此,Test.test
不能 return 对 TestStruct.test
的引用。在 Test
的多个实现的情况下,这也将是模棱两可的。
结论:不能引用协议的方法实现,因为它们没有实现。
给定以下结构:
struct TestStruct {
func test() {
print("Something")
}
}
像这样引用 test
函数有效:
let testFunc = TestStruct.test // (TestStruct) -> () -> Void
为了执行该功能,您必须执行以下操作:
testFunc(TestStruct())() // Prints "Something"
假设你让 TestStruct
遵守一个协议:
protocol Test {
func test()
}
extension TestStruct: Test {}
现在尝试像这样通过协议引用 test
函数是行不通的:
let testFunc = Test.func // Does not compile, no error message
testFunc
的类型不应该是(Test) -> () -> Void
吗?为什么现在正在编译?
根据 SR-75,您编写的代码旨在在某些时候工作。他们还没有实施。
编译器崩溃而不是打印错误这一事实意味着您发现了编译器错误。
:; xcrun swift
Welcome to Apple Swift version 4.0 (swiftlang-900.0.54.10 clang-900.0.31). Type :help for assistance.
1> struct TestStruct {
2. func test() {
3. print("Something")
4. }
5. }
6> protocol Test {
7. func test()
8. }
9.
10. extension TestStruct: Test {}
11> let testFunc = Test.test
Segmentation fault: 11
“Segmentation fault: 11”表示编译器崩溃。 您应该去 https://bugs.swift.org/,如果您没有帐户,请创建一个帐户,然后提交错误报告。
您可以通过将测试代码放入文件并编译它来查看编译器堆栈跟踪:
:; echo 'protocol Test { func test() }; let testFunc = Test.test' > main.swift && xcrun swiftc main.swift
0 swift 0x000000010b5efeaa PrintStackTraceSignalHandler(void*) + 42
1 swift 0x000000010b5ef2e6 SignalHandler(int) + 662
2 libsystem_platform.dylib 0x00007fff9742fb3a _sigtramp + 26
3 libsystem_platform.dylib 0x00007f82e307de00 _sigtramp + 1271194336
4 swift 0x0000000108818c2c swift::Lowering::SILGenFunction::manageOpaqueValue(swift::Lowering::SILGenFunction::OpaqueValueState&, swift::SILLocation, swift::Lowering::SGFContext) + 188
5 swift 0x000000010882fa1b swift::ASTVisitor<(anonymous namespace)::RValueEmitter, swift::Lowering::RValue, void, void, void, void, void, swift::Lowering::SGFContext>::visit(swift::Expr*, swift::Lowering::SGFContext) + 11067
6 swift 0x000000010882d6a1 swift::ASTVisitor<(anonymous namespace)::RValueEmitter, swift::Lowering::RValue, void, void, void, void, void, swift::Lowering::SGFContext>::visit(swift::Expr*, swift::Lowering::SGFContext) + 1985
7 swift 0x0000000108838f01 swift::ASTVisitor<(anonymous namespace)::RValueEmitter, swift::Lowering::RValue, void, void, void, void, void, swift::Lowering::SGFContext>::visit(swift::Expr*, swift::Lowering::SGFContext) + 49185
8 swift 0x0000000108849329 void llvm::function_ref<void (swift::Expr*)>::callback_fn<swift::Lowering::RValue swift::Lowering::SILGenFunction::emitOpenExistentialExpr<swift::Lowering::RValue, (anonymous namespace)::RValueEmitter::visitOpenExistentialExpr(swift::OpenExistentialExpr*, swift::Lowering::SGFContext)::$_5>(swift::OpenExistentialExpr*, (anonymous namespace)::RValueEmitter::visitOpenExistentialExpr(swift::OpenExistentialExpr*, swift::Lowering::SGFContext)::$_5)::'lambda'(swift::Expr*)>(long, swift::Expr*) + 41
9 swift 0x00000001088499e7 swift::Lowering::SILGenFunction::emitOpenExistentialExprImpl(swift::OpenExistentialExpr*, llvm::function_ref<void (swift::Expr*)>) + 1591
10 swift 0x000000010882e1cb swift::ASTVisitor<(anonymous namespace)::RValueEmitter, swift::Lowering::RValue, void, void, void, void, void, swift::Lowering::SGFContext>::visit(swift::Expr*, swift::Lowering::SGFContext) + 4843
11 swift 0x000000010882cb74 swift::Lowering::SILGenFunction::emitExprInto(swift::Expr*, swift::Lowering::Initialization*) + 148
12 swift 0x000000010881ccf6 swift::Lowering::SILGenFunction::emitPatternBinding(swift::PatternBindingDecl*, unsigned int) + 198
13 swift 0x00000001087ce3cf swift::ASTVisitor<swift::Lowering::SILGenModule, void, void, void, void, void, void>::visit(swift::Decl*) + 559
14 swift 0x00000001087cd4ab swift::Lowering::SILGenModule::emitSourceFile(swift::SourceFile*, unsigned int) + 1115
15 swift 0x00000001087cee39 swift::SILModule::constructSIL(swift::ModuleDecl*, swift::SILOptions&, swift::FileUnit*, llvm::Optional<unsigned int>, bool) + 841
16 swift 0x0000000107f6dedc performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) + 13020
17 swift 0x0000000107f69394 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 7332
18 swift 0x0000000107f1ead8 main + 12248
19 libdyld.dylib 0x00007fff97220235 start + 1
20 libdyld.dylib 0x000000000000000f start + 1759378907
Stack dump:
0. Program arguments: /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -c -primary-file main.swift -target x86_64-apple-macosx10.9 -enable-objc-interop -sdk /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk -color-diagnostics -module-name main -o /var/folders/kn/1d839myx4tlghz34f_lh3hvc0000gn/T/main-65ce73.o
<unknown>:0: error: unable to execute command: Segmentation fault: 11
<unknown>:0: error: compile command failed due to signal 11 (use -v to see invocation)
你的结构和你的协议之间的区别是协议没有实现方法test
。它只是声明了一个名为 test
的方法。表达式 TestStruct.test
return 是对结构的方法 test
实现的引用。因为该协议没有 test
的实现,编译器无法 return 对此的引用。
注意:协议 Test
不 知道 关于其实现 类 或结构的任何信息。因此,Test.test
不能 return 对 TestStruct.test
的引用。在 Test
的多个实现的情况下,这也将是模棱两可的。
结论:不能引用协议的方法实现,因为它们没有实现。