Description
Previous ID | SR-10547 |
Radar | rdar://problem/50207523 |
Original Reporter | @ghugues |
Type | Bug |
Attachment: Download
Additional Detail from JIRA
Votes | 0 |
Component/s | Compiler |
Labels | Bug, 5.0Regression, RunTimeCrash |
Assignee | None |
Priority | Medium |
md5: 7cca5f7cab0ff32756235f128b90b95f
Issue Description:
When a class that is only available starting with a given version of iOS implements a Swift only protocol, a crash occurs when testing conformance to this protocol on previous versions of iOS.
The following example crashes on all versions of iOS below iOS 12.0 :
protocol TestProtocol { }
@available(iOS 12.0, *)
class iOS12OnlySubclass: UITextInputPasswordRules, TestProtocol { }
func testCrash() {
let instance = NSObject() // Can be anything
_ = instance is TestProtocol // Crashes here
}
testCrash()
The UITextInputPasswordRules
is just an example of a class that was introduced in iOS 12, any other class introduced in iOS 12 will cause the same crash.
iOS 12 is just an example of a version of iOS. If the class is only available in iOS n, then the crash occurs on all versions of iOS less than n.
This bug was introduced in Xcode 10.2 and does not seem to occur in Xcode 10.1
Compiled with Xcode 10.2, Swift 5.0 -> Crash
Compiled with Xcode 10.2, Swift 4.2 -> Crash
Compiled with Xcode 10.1, Swift 4.2 -> No crash
Workaround: If the protocol TestProtocol
is declared @objc
, no crash occurs.
Stacktrace :
* thread #​1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
frame #​0: 0x0000000109a6c19f CoreFoundation`___forwarding___ + 1471
frame #​1: 0x0000000109a6bb58 CoreFoundation`__forwarding_prep_0___ + 120
frame #​2: 0x0000000105b93a14 libobjc.A.dylib`CALLING_SOME_+initialize_METHOD + 19
frame #​3: 0x0000000105b93dae libobjc.A.dylib`_class_initialize + 276
frame #​4: 0x0000000105b9a5e7 libobjc.A.dylib`lookUpImpOrForward + 225
frame #​5: 0x0000000105baa3d4 libobjc.A.dylib`_objc_msgSend_uncached + 68
frame #​6: 0x000000010527cde5 TestApp`type metadata accessor for iOS12OnlySubclass at <compiler-generated>:0
frame #​7: 0x0000000108d0747c libswiftCore.dylib`swift::TargetProtocolConformanceDescriptor<swift::InProcess>::getCanonicalTypeMetadata() const + 172
frame #​8: 0x0000000108d08564 libswiftCore.dylib`swift_conformsToSwiftProtocolImpl(swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptor<swift::InProcess> const*, llvm::StringRef) + 292
frame #​9: 0x0000000108d08348 libswiftCore.dylib`swift_conformsToProtocol + 152
frame #​10: 0x0000000108cdcd8a libswiftCore.dylib`swift::_conformsToProtocol(swift::OpaqueValue const*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptorRef<swift::InProcess>, swift::TargetWitnessTable<swift::InProcess> const**) + 42
frame #​11: 0x0000000108ce0b97 libswiftCore.dylib`_conformsToProtocols(swift::OpaqueValue const*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetExistentialTypeMetadata<swift::InProcess> const*, swift::TargetWitnessTable<swift::InProcess> const**) + 231
frame #​12: 0x0000000108cdff69 libswiftCore.dylib`_dynamicCastToExistential(swift::OpaqueValue*, swift::OpaqueValue*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetExistentialTypeMetadata<swift::InProcess> const*, swift::DynamicCastFlags) + 489
* frame #​13: 0x000000010527d02a TestApp`testCrash() at AppDelegate.swift:19:18
Console logs :
TestApp[18250:3491571] *** NSForwarding: warning: object 0x1052812f8 of class 'TestApp.iOS12OnlySubclass' does not implement methodSignatureForSelector: -- did you forget to declare the superclass of 'TestApp.iOS12OnlySubclass'?
TestApp[18250:3491571] *** NSForwarding: warning: object 0x1052812f8 of class 'TestApp.iOS12OnlySubclass' does not implement doesNotRecognizeSelector: -- abort