blob: 2786902058511b0482037ed390420a6edd74aa36 [file] [log] [blame]
// RUN: %target-run-simple-swift | %FileCheck %s
// REQUIRES: executable_test
// rdar://problem/27616753
// XFAIL: *
// REQUIRES: objc_interop
import Foundation
@objc protocol SwiftObjCProto {}
class SwiftSuperPort : Port { }
class SwiftSubPort : SwiftSuperPort { }
class SwiftSuper { }
class SwiftSub : SwiftSuper { }
extension Port : SwiftObjCProto {}
var obj : AnyObject
func genericCast<T>(_ x: AnyObject, _: T.Type) -> T? {
return x as? T
}
func genericCastObjCBound<T: NSObject>(_ x: AnyObject, _: T.Type) -> T? {
return x as? T
}
// Test instance of Swift subclass of Objective-C class
obj = SwiftSubPort()
_ = obj as! SwiftSubPort
_ = obj as! SwiftSuperPort
_ = (obj as? Port)
_ = (obj as? NSObject)!
if (obj as? SwiftSubPort) == nil { abort() }
if (obj as? SwiftSuperPort) == nil { abort() }
if (obj as? Port) == nil { abort() }
if (obj as? NSObject) == nil { abort() }
if (obj as? NSArray) != nil { abort() }
if (obj as? SwiftSub) != nil { abort() }
if (obj as? SwiftSuper) != nil { abort() }
obj = SwiftSuperPort()
_ = obj as! SwiftSuperPort
_ = obj as! Port
_ = obj as! NSObject
if (obj as? SwiftSubPort) != nil { abort() }
if (obj as? SwiftSuperPort) == nil { abort() }
if (obj as? Port) == nil { abort() }
if (obj as? NSObject) == nil { abort() }
if (obj as? NSArray) != nil { abort() }
if (obj as? SwiftSub) != nil { abort() }
if (obj as? SwiftSuper) != nil { abort() }
// Test instance of Objective-C class that has Swift subclass
obj = Port()
_ = obj as! Port
_ = obj as! NSObject
if (obj as? SwiftSubPort) != nil { abort() }
if (obj as? SwiftSuperPort) != nil { abort() }
if (obj as? Port) == nil { abort() }
if (obj as? NSObject) == nil { abort() }
if (obj as? NSArray) != nil { abort() }
if (obj as? SwiftSub) != nil { abort() }
if (obj as? SwiftSuper) != nil { abort() }
if (obj as? SwiftObjCProto) == nil { abort() }
obj = Port()
_ = genericCast(obj, Port.self)!
_ = genericCast(obj, NSObject.self)!
if genericCast(obj, SwiftSubPort.self) != nil { abort() }
if genericCast(obj, SwiftSuperPort.self) != nil { abort() }
if genericCast(obj, Port.self) == nil { abort() }
if genericCast(obj, NSObject.self) == nil { abort() }
if genericCast(obj, NSArray.self) != nil { abort() }
if genericCast(obj, SwiftSub.self) != nil { abort() }
if genericCast(obj, SwiftSuper.self) != nil { abort() }
_ = genericCastObjCBound(obj, Port.self)!
_ = genericCastObjCBound(obj, NSObject.self)!
if genericCastObjCBound(obj, SwiftSubPort.self) != nil { abort() }
if genericCastObjCBound(obj, SwiftSuperPort.self) != nil { abort() }
if genericCastObjCBound(obj, Port.self) == nil { abort() }
if genericCastObjCBound(obj, NSObject.self) == nil { abort() }
if genericCastObjCBound(obj, NSArray.self) != nil { abort() }
obj = NSObject()
_ = obj as! NSObject
if (obj as? SwiftSubPort) != nil { abort() }
if (obj as? SwiftSuperPort) != nil { abort() }
if (obj as? Port) != nil { abort() }
if (obj as? NSObject) == nil { abort() }
if (obj as? NSCopying) != nil { abort() }
if (obj as? NSArray) != nil { abort() }
if (obj as? SwiftSub) != nil { abort() }
if (obj as? SwiftSuper) != nil { abort() }
if (obj as? SwiftObjCProto) != nil { abort() }
// Test instance of a tagged pointer type
obj = NSNumber(value: 1234567)
_ = obj as! NSNumber
_ = obj as! NSValue
_ = obj as! NSObject
_ = obj as! NSCopying
if (obj as? SwiftSubPort) != nil { abort() }
if (obj as? SwiftSuperPort) != nil { abort() }
if (obj as? NSNumber) == nil { abort() }
if (obj as? NSValue) == nil { abort() }
if (obj as? NSObject) == nil { abort() }
if (obj as? NSCopying) == nil { abort() }
if (obj as? NSArray) != nil { abort() }
if (obj as? SwiftSub) != nil { abort() }
if (obj as? SwiftSuper) != nil { abort() }
// Test instance of a Swift class with no Objective-C inheritance
obj = SwiftSub()
_ = obj as! SwiftSub
_ = obj as! SwiftSuper
if (obj as? SwiftSubPort) != nil { abort() }
if (obj as? SwiftSuperPort) != nil { abort() }
if (obj as? NSObject) != nil { abort() }
if (obj as? NSArray) != nil { abort() }
if (obj as? SwiftSub) == nil { abort() }
if (obj as? SwiftSuper) == nil { abort() }
obj = SwiftSuper()
_ = obj as! SwiftSuper
if (obj as? SwiftSubPort) != nil { abort() }
if (obj as? SwiftSuperPort) != nil { abort() }
if (obj as? NSObject) != nil { abort() }
if (obj as? NSArray) != nil { abort() }
if (obj as? SwiftSub) != nil { abort() }
if (obj as? SwiftSuper) == nil { abort() }
// Test optional and non-optional bridged conversions
var ao: AnyObject = "s"
ao as! String
ao is String
var auo: AnyObject! = "s"
var s: String = auo as! String
var auoo: AnyObject? = "s"
auoo! as? String
// Test bridged casts.
// CHECK: Downcast to hello
obj = NSString(string: "hello")
if let str = obj as? String {
print("Downcast to \(str)")
} else {
print("Not a string?")
}
// Forced cast using context
// CHECK-NEXT: Forced to string hello
let forcedStr: String = obj as! String
print("Forced to string \(forcedStr)")
// CHECK-NEXT: Downcast to Swift
var objOpt: AnyObject? = NSString(string: "Swift")
if let str = objOpt as? String {
print("Downcast to \(str)")
} else {
print("Not a string?")
}
// Forced cast using context
// CHECK-NEXT: Forced to string Swift
let forcedStrOpt: String = objOpt as! String
print("Forced to string \(forcedStrOpt)")
// CHECK-NEXT: Downcast to world
var objImplicitOpt: AnyObject! = NSString(string: "world")
if let str = objImplicitOpt as? String {
print("Downcast to \(str)")
} else {
print("Not a string?")
}
// Forced cast using context
// CHECK-NEXT: Forced to string world
let forcedStrImplicitOpt: String = objImplicitOpt as! String
print("Forced to string \(forcedStrImplicitOpt)")
// CHECK-NEXT: Downcast correctly failed due to nil
objOpt = nil
if let str = objOpt as? String {
print("Downcast should not succeed for nil")
} else {
print("Downcast correctly failed due to nil")
}
// CHECK-NEXT: Downcast correctly failed due to nil
objImplicitOpt = nil
if let str = objImplicitOpt as? String {
print("Downcast should not succeed for nil")
} else {
print("Downcast correctly failed due to nil")
}
// Test bridged "isa" checks.
// CHECK: It's a string!
obj = NSString(string: "hello")
if obj is String {
print("It's a string!")
} else {
print("Not a string?")
}
// CHECK-NEXT: It's a string!
objOpt = NSString(string: "Swift")
if objOpt is String {
print("It's a string!")
} else {
print("Not a string?")
}
// CHECK-NEXT: It's a string!
objImplicitOpt = NSString(string: "world")
if objImplicitOpt is String {
print("It's a string!")
} else {
print("Not a string?")
}
// CHECK-NEXT: Isa correctly failed due to nil
objOpt = nil
if objOpt is String {
print("Isa should not succeed for nil")
} else {
print("Isa correctly failed due to nil")
}
// CHECK-NEXT: Isa correctly failed due to nil
objImplicitOpt = nil
if objImplicitOpt is String {
print("Isa should not succeed for nil")
} else {
print("Isa correctly failed due to nil")
}
let words = ["Hello", "Swift", "World"]
// CHECK-NEXT: Object-to-bridged-array cast produced ["Hello", "Swift", "World"]
obj = words as AnyObject
if let strArr = obj as? [String] {
print("Object-to-bridged-array cast produced \(strArr)")
} else {
print("Object-to-bridged-array cast failed")
}
// Check downcast from the bridged type itself.
// CHECK-NEXT: NSArray-to-bridged-array cast produced ["Hello", "Swift", "World"]
var nsarr = words as NSArray
if let strArr = nsarr as? [String] {
print("NSArray-to-bridged-array cast produced \(strArr)")
} else {
print("NSArray-to-bridged-array cast failed")
}
// CHECK-NEXT: NSArray?-to-bridged-array cast produced ["Hello", "Swift", "World"]
var nsarrOpt = words as NSArray?
if let strArr = nsarrOpt as? [String] {
print("NSArray?-to-bridged-array cast produced \(strArr)")
} else {
print("NSArray?-to-bridged-array cast failed")
}
// CHECK-NEXT: NSArray!-to-bridged-array cast produced ["Hello", "Swift", "World"]
var nsarrImplicitOpt = words as NSArray!
if let strArr = nsarrImplicitOpt as? [String] {
print("NSArray!-to-bridged-array cast produced \(strArr)")
} else {
print("NSArray!-to-bridged-array cast failed")
}
// Check downcast from a superclass of the bridged type.
// CHECK-NEXT: NSObject-to-bridged-array cast produced ["Hello", "Swift", "World"]
var nsobj: NSObject = nsarr
if let strArr = nsobj as? [String] {
print("NSObject-to-bridged-array cast produced \(strArr)")
} else {
print("NSObject-to-bridged-array cast failed")
}
// CHECK-NEXT: NSArray is [String]
if nsarr is [String] {
print("NSArray is [String]")
} else {
print("NSArray is not a [String]")
}
// CHECK-NEXT: NSArray? is [String]
if nsarrOpt is [String] {
print("NSArray? is [String]")
} else {
print("NSArray? is not a [String]")
}
// CHECK-NEXT: NSArray! is [String]
if nsarrImplicitOpt is [String] {
print("NSArray! is [String]")
} else {
print("NSArray! is not a [String]")
}
// CHECK-NEXT: NSObject is [String]
if nsobj is [String] {
print("NSObject is [String]")
} else {
print("NSObject is not a [String]")
}
// Forced downcast based on context.
// CHECK-NEXT: Forced to string array ["Hello", "Swift", "World"]
var forcedStrArray: [String] = obj as! [String]
print("Forced to string array \(forcedStrArray)")
// CHECK-NEXT: Forced NSArray to string array ["Hello", "Swift", "World"]
forcedStrArray = nsarr as! [String]
print("Forced NSArray to string array \(forcedStrArray)")
// CHECK-NEXT: Forced NSArray? to string array ["Hello", "Swift", "World"]
forcedStrArray = nsarrOpt as! [String]
print("Forced NSArray? to string array \(forcedStrArray)")
// CHECK-NEXT: Forced NSArray! to string array ["Hello", "Swift", "World"]
forcedStrArray = nsarrImplicitOpt as! [String]
print("Forced NSArray! to string array \(forcedStrArray)")
// CHECK-NEXT: Object-to-array cast produced [Hello, Swift, World]
if let strArr = obj as? [NSString] {
print("Object-to-array cast produced \(strArr)")
} else {
print("Object-to-array cast failed")
}
// CHECK-NEXT: Object-to-bridged-array cast failed due to bridge mismatch
if let strArr = obj as? [Int] {
print("Object-to-bridged-array cast should not have succeeded")
} else {
print("Object-to-bridged-array cast failed due to bridge mismatch")
}
// CHECK-NEXT: Array of strings is not an array of ints
if obj is [Int] {
print("Array of strings should not be an array of ints!")
} else {
print("Array of strings is not an array of ints")
}
// Implicitly unwrapped optional of object to array casts.
// CHECK-NEXT: Object-to-bridged-array cast produced ["Hello", "Swift", "World"]
objOpt = words as AnyObject?
if let strArr = objOpt as? [String] {
print("Object-to-bridged-array cast produced \(strArr)")
} else {
print("Object-to-bridged-array cast failed")
}
// Forced downcast based on context.
// CHECK-NEXT: Forced to string array ["Hello", "Swift", "World"]
let forcedStrArrayOpt: [String] = objOpt as! [String]
print("Forced to string array \(forcedStrArrayOpt)")
// CHECK-NEXT: Object-to-array cast produced [Hello, Swift, World]
if let strArr = objOpt as? [NSString] {
print("Object-to-array cast produced \(strArr)")
} else {
print("Object-to-array cast failed")
}
// CHECK: Object-to-bridged-array cast failed due to bridge mismatch
if let intArr = objOpt as? [Int] {
print("Object-to-bridged-array cast should not have succeeded")
} else {
print("Object-to-bridged-array cast failed due to bridge mismatch")
}
// CHECK: Object-to-bridged-array cast failed due to nil
objOpt = nil
if let strArr = objOpt as? [String] {
print("Cast from nil succeeded?")
} else {
print("Object-to-bridged-array cast failed due to nil")
}
// Optional of object to array casts.
// CHECK-NEXT: Object-to-bridged-array cast produced ["Hello", "Swift", "World"]
objImplicitOpt = words as AnyObject!
if let strArr = objImplicitOpt as? [String] {
print("Object-to-bridged-array cast produced \(strArr)")
} else {
print("Object-to-bridged-array cast failed")
}
// Forced downcast based on context.
// CHECK-NEXT: Forced to string array ["Hello", "Swift", "World"]
let forcedStrArrayImplicitOpt: [String] = objImplicitOpt as! [String]
print("Forced to string array \(forcedStrArrayImplicitOpt)")
// CHECK-NEXT: Object-to-array cast produced [Hello, Swift, World]
if let strArr = objImplicitOpt as? [NSString] {
print("Object-to-array cast produced \(strArr)")
} else {
print("Object-to-array cast failed")
}
// CHECK: Object-to-bridged-array cast failed due to bridge mismatch
if let intArr = objImplicitOpt as? [Int] {
print("Object-to-bridged-array cast should not have succeeded")
} else {
print("Object-to-bridged-array cast failed due to bridge mismatch")
}
// CHECK: Object-to-bridged-array cast failed due to nil
objImplicitOpt = nil
if let strArr = objImplicitOpt as? [String] {
print("Cast from nil succeeded?")
} else {
print("Object-to-bridged-array cast failed due to nil")
}
// Casting an array of numbers to different numbers.
// CHECK: Numbers-as-doubles cast produces [3.9375, 2.71828, 0.0]
obj = ([3.9375, 2.71828, 0] as [Double]) as AnyObject
if let doubleArr = obj as? [Double] {
print(MemoryLayout<Double>.size)
print("Numbers-as-doubles cast produces \(doubleArr)")
} else {
print("Numbers-as-doubles failed")
}
// CHECK: Numbers-as-floats cast produces [3.9375, 2.71828{{.*}}, 0.0]
if let floatArr = obj as? [Float] {
print(MemoryLayout<Float>.size)
print("Numbers-as-floats cast produces \(floatArr)")
} else {
print("Numbers-as-floats failed")
}
// CHECK: Numbers-as-ints cast produces [3, 2, 0]
if let intArr = obj as? [Int] {
print("Numbers-as-ints cast produces \(intArr)")
} else {
print("Numbers-as-ints failed")
}
// CHECK: Numbers-as-bools cast produces [true, true, false]
if let boolArr = obj as? [Bool] {
print("Numbers-as-bools cast produces \(boolArr)")
} else {
print("Numbers-as-bools failed")
}
class Base : NSObject {
override var description: String {
return "Base"
}
}
class Derived : Base {
override var description: String {
return "Derived"
}
}
// CHECK: Array-of-base cast produces [Derived, Derived, Base]
obj = [Derived(), Derived(), Base()]
if let baseArr = obj as? [Base] {
print("Array-of-base cast produces \(baseArr)")
} else {
print("Not an array of base")
}
// CHECK: Not an array of derived
if let derivedArr = obj as? [Derived] {
print("Array-of-derived cast produces \(derivedArr)")
} else {
print("Not an array of derived")
}
// CHECK: Dictionary-of-base-base cast produces
obj = [Derived() : Derived(), Derived() : Base(), Derived() : Derived() ] as AnyObject
if let baseDict = obj as? Dictionary<Base, Base> {
print("Dictionary-of-base-base cast produces \(baseDict)")
} else {
print("Not a dictionary of base/base")
}
// CHECK: Dictionary-of-derived-base cast produces
if let baseDict = obj as? Dictionary<Derived, Base> {
print("Dictionary-of-derived-base cast produces \(baseDict)")
} else {
print("Not a dictionary of derived/base")
}
// CHECK: Not a dictionary of derived/derived
if let dict = obj as? Dictionary<Derived, Derived> {
print("Dictionary-of-derived-derived cast produces \(dict)")
} else {
print("Not a dictionary of derived/derived")
}
let strArray: AnyObject = ["hello", "world"]
let intArray: AnyObject = [1, 2, 3]
let dictArray: AnyObject = [["hello" : 1, "world" : 2],
["swift" : 1, "speedy" : 2]]
// CHECK: Dictionary<String, AnyObject> is
obj = ["a" : strArray, "b" : intArray, "c": dictArray]
if let dict = obj as? Dictionary<String, [AnyObject]> {
print("Dictionary<String, AnyObject> is \(dict)")
} else {
print("Not a Dictionary<String, AnyObject>")
}
// CHECK: Not a Dictionary<String, String>
if let dict = obj as? Dictionary<String, [String]> {
print("Dictionary<String, String> is \(dict)")
} else {
print("Not a Dictionary<String, String>")
}
// CHECK: Not a Dictionary<String, Int>
if let dict = obj as? Dictionary<String, [Int]> {
print("Dictionary<String, Int> is \(dict)")
} else {
print("Not a Dictionary<String, Int>")
}
// CHECK: [Dictionary<String, Int>] is
obj = dictArray
if let array = obj as? [Dictionary<String, Int>] {
print("[Dictionary<String, Int>] is \(array)")
} else {
print("Not a [Dictionary<String, Int>]")
}
// CHECK: Not a [Dictionary<String, String>]
if let array = obj as? [Dictionary<String, String>] {
print("[Dictionary<String, String>] is \(array)")
} else {
print("Not a [Dictionary<String, String>]")
}
// CHECK: Dictionary<String, [Dictionary<String, Int>]> is ["a": [
obj = ["a" : dictArray]
if let dict = obj as? Dictionary<String, [Dictionary<String, Int>]> {
print("Dictionary<String, [Dictionary<String, Int>]> is \(dict)")
} else {
print("Not a Dictionary<String, [Dictionary<String, Int>]>")
}
// CHECK: Not a Dictionary<String, [Dictionary<String, String>]>
if let dict = obj as? Dictionary<String, [Dictionary<String, String>]> {
print("Dictionary<String, [Dictionary<String, String>]> is \(dict)")
} else {
print("Not a Dictionary<String, [Dictionary<String, String>]>")
}
// CHECK: [Dictionary<String, [Dictionary<String, Int>]>] is
obj = [obj, obj, obj]
if let array = obj as? [Dictionary<String, [Dictionary<String, Int>]>] {
print("[Dictionary<String, [Dictionary<String, Int>]>] is \(array)")
} else {
print("Not a [Dictionary<String, [Dictionary<String, Int>]>]")
}
// CHECK: Not a Dictionary<String, [Dictionary<String, String>]>[]
if let array = obj as? Dictionary<String, [Dictionary<String, String>]> {
print("Dictionary<String, [Dictionary<String, String>]>[] is \(array)")
} else {
print("Not a Dictionary<String, [Dictionary<String, String>]>[]")
}
// Helper function that downcasts
func downcastToStringArrayOptOpt(_ obj: AnyObject???!) {
if let strArrOptOpt = obj as? [String]?? {
if let strArrOpt = strArrOptOpt {
if let strArr = strArrOpt {
print("some(some(some(\(strArr))))")
} else {
print("some(some(none))")
}
} else {
print("some(none)")
}
} else {
print("none")
}
}
// CHECK: {{^}}some(some(some(["a", "b", "c"]))){{$}}
var objOptOpt: AnyObject?? = .some(.some(["a", "b", "c"]))
downcastToStringArrayOptOpt(objOptOpt)
// CHECK: {{^}}none{{$}}
objOptOpt = .some(.some([1 : "hello", 2 : "swift", 3 : "world"]))
downcastToStringArrayOptOpt(objOptOpt)
// CHECK: {{^}}none{{$}}
objOptOpt = .some(.some([1, 2, 3]))
downcastToStringArrayOptOpt(objOptOpt)
print("ok") // CHECK: ok