// RUN: %target-run-simple-swift | FileCheck %s // REQUIRES: executable_test // REQUIRES: objc_interop // Test dynamic casts that bridge value types through the runtime. import Foundation func genericForcedCast(a: T) -> U { return a as! U } func genericConditionalCast(a: T) -> U? { return a as? U } func testForcedValueToObjectBridging() { // CHECK: ---Forced value to object bridging--- print("---Forced value to object bridging---") let array: [String] = ["Hello", "World"] // Forced bridging (exact) // CHECK-NEXT: ( // CHECK-NEXT: Hello, // CHECK-NEXT: World // CHECK-NEXT: ) print(genericForcedCast(array) as NSArray) // Forced bridging (superclass) // CHECK-NEXT: ( // CHECK-NEXT: Hello, // CHECK-NEXT: World // CHECK-NEXT: ) print(genericForcedCast(array) as NSObject) // Forced bridging (AnyObject) // CHECK-NEXT: ( // CHECK-NEXT: Hello, // CHECK-NEXT: World // CHECK-NEXT: ) print(genericForcedCast(array) as NSObject) // Forced bridging (existential success) // CHECK-NEXT: ( // CHECK-NEXT: Hello, // CHECK-NEXT: World // CHECK-NEXT: ) print(genericForcedCast(array) as NSCoding) print("Done") } // CHECK: Done testForcedValueToObjectBridging() func testConditionalValueToObjectBridging() { // CHECK: ---Conditional value to object bridging--- print("---Conditional value to object bridging---") let array: [String] = ["Hello", "World"] // Conditional bridging (exact) // CHECK-NEXT: ( // CHECK-NEXT: Hello, // CHECK-NEXT: World // CHECK-NEXT: ) if let nsArray = (genericConditionalCast(array) as NSArray?) { print("\(nsArray)") } else { print("Not an NSArray") } // Conditional bridging (superclass) // CHECK-NEXT: ( // CHECK-NEXT: Hello, // CHECK-NEXT: World // CHECK-NEXT: ) if let nsObject = (genericConditionalCast(array) as NSObject?) { print("\(nsObject)") } else { print("Not an NSObject") } // Conditional bridging (AnyObject) // CHECK-NEXT: ( // CHECK-NEXT: Hello, // CHECK-NEXT: World // CHECK-NEXT: ) if let anyObject = (genericConditionalCast(array) as AnyObject?) { print("\(anyObject)") } else { print("Not an AnyObject") } // Conditional bridging (existential success) // CHECK-NEXT: ( // CHECK-NEXT: Hello, // CHECK-NEXT: World // CHECK-NEXT: ) if let coding = (genericConditionalCast(array) as NSCoding?) { print("\(coding)") } else { print("Not an NSCoding") } // CHECK-NEXT: NSXMLParserDelegate if let delegate = (genericConditionalCast(array) as NSXMLParserDelegate?) { print("\(delegate)") } else { print("Not an NSXMLParserDelegate") } // Conditional bridging (unrelated class) // CHECK-NEXT: Not an NSString if let nsString = (genericConditionalCast(array) as NSString?) { print("\(nsString)") } else { print("Not an NSString") } print("Done") } // CHECK: Done testConditionalValueToObjectBridging() func testForcedObjectToValueBridging() { // CHECK: ---Forced object to value bridging--- print("---Forced object to value bridging---") let nsArray: NSArray = ["Hello", "World"] // Forced bridging (exact) // CHECK: ["Hello", "World"] print(genericForcedCast(nsArray) as [String]) // Forced bridging (superclass) // CHECK: ["Hello", "World"] let nsObject: NSObject = nsArray print(genericForcedCast(nsObject) as [String]) // Forced bridging (AnyObject) // CHECK: ["Hello", "World"] let anyObject: AnyObject = nsArray print(genericForcedCast(anyObject) as [String]) // Forced bridging (existential success) let nsCoding: NSCoding = nsArray print(genericForcedCast(nsCoding) as [String]) print("Done") } // CHECK: Done testForcedObjectToValueBridging() func testConditionalObjectToValueBridging() { // CHECK: ---Conditional object to value bridging--- print("---Conditional object to value bridging---") let nsArray: NSArray = ["Hello", "World"] let nsObject: NSObject = nsArray let anyObject: AnyObject = nsArray let nsCoding: NSCoding = nsArray let nsString: NSString = "Hello" // Conditional bridging (exact) // CHECK: ["Hello", "World"] if let arr = (genericConditionalCast(nsArray) as [String]?) { print(arr) } else { print("Not a [String]") } // Conditional bridging (superclass) // CHECK: ["Hello", "World"] if let arr = (genericConditionalCast(nsObject) as [String]?) { print(arr) } else { print("Not a [String]") } // Conditional bridging (AnyObject) // CHECK: ["Hello", "World"] if let arr = (genericConditionalCast(anyObject) as [String]?) { print(arr) } else { print("Not a [String]") } // Conditional bridging (existential success) // CHECK: ["Hello", "World"] if let arr = (genericConditionalCast(nsCoding) as [String]?) { print(arr) } else { print("Not a [String]") } // Conditional bridging (existential failure) // Not a [Int] if let arr = (genericConditionalCast(nsCoding) as [Int]?) { print(arr) } else { print("Not a [String]") } // Conditional bridging (unrelated class type) // CHECK: Not a [String] if let arr = (genericConditionalCast(nsString) as [String]?) { print(arr) } else { print("Not a [String]") } // Conditional bridging (unrelated element type) // CHECK: Not a [Int] if let arr = (genericConditionalCast(nsArray) as [Int]?) { print(arr) } else { print("Not a [Int]") } print("Done") } // CHECK: Done testConditionalObjectToValueBridging() // rdar://problem/22587077 class Canary: NSObject { deinit { print("died") } } var CanaryAssocObjectHandle = 0 func testValueToObjectBridgingInSwitch() { autoreleasepool { let string = "hello" let nsString = string as NSString objc_setAssociatedObject(nsString, &CanaryAssocObjectHandle, Canary(), .OBJC_ASSOCIATION_RETAIN_NONATOMIC) switch nsString as AnyObject { case let s as String: print("Got string \(s)") default: print("Not a string") } } print("Done") } // CHECK: died // CHECK: Done testValueToObjectBridgingInSwitch()