// -*- swift -*- // RUN: %target-run-simple-swiftgyb // REQUIRES: executable_test // FIXME: Casting.cpp has dozens of places to fail a cast. This test does not // attempt to enumerate them all. import StdlibUnittest #if _runtime(_ObjC) import Foundation #endif % types = [] % objectTypes = [] % protocolTypes = [] % ObjCTypes = [] % types.append(['main.Class1', 'main.Class2']) % objectTypes.append(['main.Class1', 'main.Class2']) class Class1 { } class Class2 { } % types.append(['main.Struct1', 'main.Struct2']) struct Struct1 { } struct Struct2 { } % types.append(['main.ObjCClass1', 'main.ObjCClass2']) % objectTypes.append(['main.ObjCClass1', 'main.ObjCClass2']) % ObjCTypes.extend(['main.ObjCClass1', 'main.ObjCClass2']) #if _runtime(_ObjC) class ObjCClass1 : NSObject { } class ObjCClass2 : NSObject { } #endif % types.append(['DateFormatter', 'NumberFormatter']) % objectTypes.append(['DateFormatter', 'NumberFormatter']) % ObjCTypes.extend(['DateFormatter', 'NumberFormatter']) // non-Swift Objective-C class % protocolTypes.append('main.Proto1') % protocolTypes.append('main.Proto2') protocol Proto1 { } protocol Proto2 { } % protocolTypes.append('URLSessionDelegate') % ObjCTypes.append('URLSessionDelegate') // non-Swift Objective-C protocol var CastTrapsTestSuite = TestSuite("CastTraps") // Test `(T1() as Any) as T2` cast failure // for all type pairs. % for (t1, _) in types: % for (_, t2) in types: % if t1 not in ObjCTypes and t2 not in ObjCTypes: CastTrapsTestSuite.test("${t1}__${t2}") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .crashOutputMatches("Could not cast value of type '") .crashOutputMatches("${t1}' ") .crashOutputMatches(" to '") .crashOutputMatches("${t2}'") .code { let o = ${t1}() as Any expectCrashLater() let r = o as! ${t2} _blackHole(r) } % end % end % end // Test `(T1() as AnyObject) as T2` cast failure // for object type to protocol type pairs % for (t1, _) in objectTypes: % for (t2) in protocolTypes: % if t1 not in ObjCTypes and t2 not in ObjCTypes: CastTrapsTestSuite.test("${t1}__${t2}") .skip(.custom( { _isFastAssertConfiguration() }, reason: "this trap is not guaranteed to happen in -Ounchecked")) .crashOutputMatches("Could not cast value of type '") .crashOutputMatches("${t1}' ") .crashOutputMatches(" to '") .crashOutputMatches("${t2}'") .code { let o = ${t1}() as AnyObject expectCrashLater() let r = o as! ${t2} _blackHole(r) } % end % end % end protocol P2 {} if #available(SwiftStdlib 6.0, *) { CastTrapsTestSuite.test("Unexpected null") .crashOutputMatches("Found a null pointer in a value of type '") .crashOutputMatches("Foo'") .crashOutputMatches("(Detected while casting to '") .crashOutputMatches("P2'") .code { class Foo {} let n = UnsafeRawPointer(bitPattern: 0) var o: Foo = unsafeBitCast(n, to: Foo.self) let r = o as Any expectCrashLater() let s = r as? P2 _blackHole(s) } } #if _runtime(_ObjC) if #available(SwiftStdlib 6.0, *) { CastTrapsTestSuite.test("Unexpected Obj-C null") .crashOutputMatches("Found a null pointer in a value of type 'NSObject'") .crashOutputMatches("(Detected while casting to '") .crashOutputMatches("P2'") .code { let n = UnsafeRawPointer(bitPattern: 0) var o: NSObject = unsafeBitCast(n, to: NSObject.self) let r = o as Any expectCrashLater() let s = r as? P2 _blackHole(s) } } #endif class Base {} final class Derived: Base {} final class Other: Base {} @inline(never) func getDerived(_ v: Base) -> Derived { return v as! Derived } @inline(never) func getDerivedFromOptional(_ v: Base?) -> Derived { return v as! Derived } CastTrapsTestSuite.test("unconditinal fast class cast") { let c = Other() expectCrashLater() _ = getDerived(c) } CastTrapsTestSuite.test("unconditinal optional fast class cast") { let c = Other() expectCrashLater() _ = getDerivedFromOptional(c) } CastTrapsTestSuite.test("unconditinal optional nil fast class cast") { expectCrashLater() _ = getDerivedFromOptional(nil) } runAllTests()