mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Previously, we were only changing whether the object was of the right type, and not performing a deep check that (for example) the underlying array contained NSStrings for an "is String[]". Fixes the rest of <rdar://problem/16972956>. Swift SVN r18728
443 lines
13 KiB
Swift
443 lines
13 KiB
Swift
// RUN: %target-run-simple-swift | FileCheck %s
|
|
|
|
import Foundation
|
|
|
|
@objc @class_protocol protocol SwiftObjCProto {}
|
|
|
|
class SwiftSuperPort : NSPort { }
|
|
|
|
class SwiftSubPort : SwiftSuperPort { }
|
|
|
|
class SwiftSuper { }
|
|
class SwiftSub : SwiftSuper { }
|
|
|
|
extension NSPort : SwiftObjCProto {}
|
|
|
|
var obj : AnyObject
|
|
|
|
func genericCast<T>(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? NSPort)
|
|
_ = (obj as? NSObject)!
|
|
if !(obj as? SwiftSubPort) { abort() }
|
|
if !(obj as? SwiftSuperPort) { abort() }
|
|
if !(obj as? NSPort) { abort() }
|
|
if !(obj as? NSObject) { abort() }
|
|
if (obj as? NSArray) { abort() }
|
|
if (obj as? SwiftSub) { abort() }
|
|
if (obj as? SwiftSuper) { abort() }
|
|
|
|
obj = SwiftSuperPort()
|
|
_ = obj as SwiftSuperPort
|
|
_ = obj as NSPort
|
|
_ = obj as NSObject
|
|
if (obj as? SwiftSubPort) { abort() }
|
|
if !(obj as? SwiftSuperPort) { abort() }
|
|
if !(obj as? NSPort) { abort() }
|
|
if !(obj as? NSObject) { abort() }
|
|
if (obj as? NSArray) { abort() }
|
|
if (obj as? SwiftSub) { abort() }
|
|
if (obj as? SwiftSuper) { abort() }
|
|
|
|
// Test instance of Objective-C class that has Swift subclass
|
|
|
|
obj = NSPort()
|
|
_ = obj as NSPort
|
|
_ = obj as NSObject
|
|
if (obj as? SwiftSubPort) { abort() }
|
|
if (obj as? SwiftSuperPort) { abort() }
|
|
if !(obj as? NSPort) { abort() }
|
|
if !(obj as? NSObject) { abort() }
|
|
if (obj as? NSArray) { abort() }
|
|
if (obj as? SwiftSub) { abort() }
|
|
if (obj as? SwiftSuper) { abort() }
|
|
if !(obj as? SwiftObjCProto) { abort() }
|
|
|
|
obj = NSPort()
|
|
_ = genericCast(obj, NSPort.self)!
|
|
_ = genericCast(obj, NSObject.self)!
|
|
if genericCast(obj, SwiftSubPort.self) { abort() }
|
|
if genericCast(obj, SwiftSuperPort.self) { abort() }
|
|
if !genericCast(obj, NSPort.self) { abort() }
|
|
if !genericCast(obj, NSObject.self) { abort() }
|
|
if genericCast(obj, NSArray.self) { abort() }
|
|
if genericCast(obj, SwiftSub.self) { abort() }
|
|
if genericCast(obj, SwiftSuper.self) { abort() }
|
|
|
|
obj = NSObject()
|
|
_ = obj as NSObject
|
|
if (obj as? SwiftSubPort) { abort() }
|
|
if (obj as? SwiftSuperPort) { abort() }
|
|
if (obj as? NSPort) { abort() }
|
|
if !(obj as? NSObject) { abort() }
|
|
if (obj as? NSCopying) { abort() }
|
|
if (obj as? NSArray) { abort() }
|
|
if (obj as? SwiftSub) { abort() }
|
|
if (obj as? SwiftSuper) { abort() }
|
|
if (obj as? SwiftObjCProto) { abort() }
|
|
|
|
// Test instance of a tagged pointer type
|
|
|
|
obj = NSNumber(int: 1234567)
|
|
_ = obj as NSNumber
|
|
_ = obj as NSValue
|
|
_ = obj as NSObject
|
|
_ = obj as NSCopying
|
|
if (obj as? SwiftSubPort) { abort() }
|
|
if (obj as? SwiftSuperPort) { abort() }
|
|
if !(obj as? NSNumber) { abort() }
|
|
if !(obj as? NSValue) { abort() }
|
|
if !(obj as? NSObject) { abort() }
|
|
if !(obj as? NSCopying) { abort() }
|
|
if (obj as? NSArray) { abort() }
|
|
if (obj as? SwiftSub) { abort() }
|
|
if (obj as? SwiftSuper) { abort() }
|
|
|
|
// Test instance of a Swift class with no Objective-C inheritance
|
|
|
|
obj = SwiftSub()
|
|
_ = obj as SwiftSub
|
|
_ = obj as SwiftSuper
|
|
if (obj as? SwiftSubPort) { abort() }
|
|
if (obj as? SwiftSuperPort) { abort() }
|
|
if (obj as? NSObject) { abort() }
|
|
if (obj as? NSArray) { abort() }
|
|
if !(obj as? SwiftSub) { abort() }
|
|
if !(obj as? SwiftSuper) { abort() }
|
|
|
|
obj = SwiftSuper()
|
|
_ = obj as SwiftSuper
|
|
if (obj as? SwiftSubPort) { abort() }
|
|
if (obj as? SwiftSuperPort) { abort() }
|
|
if (obj as? NSObject) { abort() }
|
|
if (obj as? NSArray) { abort() }
|
|
if (obj as? SwiftSub) { abort() }
|
|
if !(obj as? SwiftSuper) { 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 {
|
|
println("Downcast to \(str)")
|
|
} else {
|
|
println("Not a string?")
|
|
}
|
|
|
|
// Forced cast using context
|
|
// CHECK-NEXT: Forced to string hello
|
|
let forcedStr: String = obj as String
|
|
println("Forced to string \(forcedStr)")
|
|
|
|
// CHECK-NEXT: Downcast to Swift
|
|
var objOpt: AnyObject? = NSString(string: "Swift")
|
|
if let str = objOpt as? String {
|
|
println("Downcast to \(str)")
|
|
} else {
|
|
println("Not a string?")
|
|
}
|
|
|
|
// Forced cast using context
|
|
// CHECK-NEXT: Forced to string Swift
|
|
let forcedStrOpt: String = objOpt as String
|
|
println("Forced to string \(forcedStrOpt)")
|
|
|
|
// CHECK-NEXT: Downcast to world
|
|
var objImplicitOpt: AnyObject! = NSString(string: "world")
|
|
if let str = objImplicitOpt as? String {
|
|
println("Downcast to \(str)")
|
|
} else {
|
|
println("Not a string?")
|
|
}
|
|
|
|
// Forced cast using context
|
|
// CHECK-NEXT: Forced to string world
|
|
let forcedStrImplicitOpt: String = objImplicitOpt as String
|
|
println("Forced to string \(forcedStrImplicitOpt)")
|
|
|
|
// CHECK-NEXT: Downcast correctly failed due to nil
|
|
objOpt = nil
|
|
if let str = objOpt as? String {
|
|
println("Downcast should not succeed for nil")
|
|
} else {
|
|
println("Downcast correctly failed due to nil")
|
|
}
|
|
|
|
// CHECK-NEXT: Downcast correctly failed due to nil
|
|
objImplicitOpt = nil
|
|
if let str = objImplicitOpt as? String {
|
|
println("Downcast should not succeed for nil")
|
|
} else {
|
|
println("Downcast correctly failed due to nil")
|
|
}
|
|
|
|
// Test bridged "isa" checks.
|
|
// CHECK: It's a string!
|
|
obj = NSString(string: "hello")
|
|
if obj is String {
|
|
println("It's a string!")
|
|
} else {
|
|
println("Not a string?")
|
|
}
|
|
|
|
// CHECK-NEXT: It's a string!
|
|
objOpt = NSString(string: "Swift")
|
|
if objOpt is String {
|
|
println("It's a string!")
|
|
} else {
|
|
println("Not a string?")
|
|
}
|
|
|
|
// CHECK-NEXT: It's a string!
|
|
objImplicitOpt = NSString(string: "world")
|
|
if objImplicitOpt is String {
|
|
println("It's a string!")
|
|
} else {
|
|
println("Not a string?")
|
|
}
|
|
|
|
// CHECK-NEXT: Isa correctly failed due to nil
|
|
objOpt = nil
|
|
if objOpt is String {
|
|
println("Isa should not succeed for nil")
|
|
} else {
|
|
println("Isa correctly failed due to nil")
|
|
}
|
|
|
|
// CHECK-NEXT: Isa correctly failed due to nil
|
|
objImplicitOpt = nil
|
|
if objImplicitOpt is String {
|
|
println("Isa should not succeed for nil")
|
|
} else {
|
|
println("Isa correctly failed due to nil")
|
|
}
|
|
|
|
// CHECK-NEXT: Object-to-bridged-array cast produced [Hello, Swift, World]
|
|
obj = ["Hello", "Swift", "World"] as String[]
|
|
if let strArr = obj as? String[] {
|
|
println("Object-to-bridged-array cast produced \(strArr)")
|
|
} else {
|
|
println("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: NSArray = ["Hello", "Swift", "World"] as String[]
|
|
if let strArr = nsarr as? String[] {
|
|
println("NSArray-to-bridged-array cast produced \(strArr)")
|
|
} else {
|
|
println("NSArray-to-bridged-array cast failed")
|
|
}
|
|
|
|
// CHECK-NEXT: NSArray?-to-bridged-array cast produced [Hello, Swift, World]
|
|
var nsarrOpt: NSArray? = ["Hello", "Swift", "World"] as String[]
|
|
if let strArr = nsarrOpt as? String[] {
|
|
println("NSArray?-to-bridged-array cast produced \(strArr)")
|
|
} else {
|
|
println("NSArray?-to-bridged-array cast failed")
|
|
}
|
|
|
|
// CHECK-NEXT: NSArray!-to-bridged-array cast produced [Hello, Swift, World]
|
|
var nsarrImplicitOpt: NSArray! = ["Hello", "Swift", "World"] as String[]
|
|
if let strArr = nsarrImplicitOpt as? String[] {
|
|
println("NSArray!-to-bridged-array cast produced \(strArr)")
|
|
} else {
|
|
println("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[] {
|
|
println("NSObject-to-bridged-array cast produced \(strArr)")
|
|
} else {
|
|
println("NSObject-to-bridged-array cast failed")
|
|
}
|
|
|
|
// CHECK-NEXT: NSArray is String[]
|
|
if nsarr is String[] {
|
|
println("NSArray is String[]")
|
|
} else {
|
|
println("NSArray is not a String[]")
|
|
}
|
|
|
|
// CHECK-NEXT: NSArray? is String[]
|
|
if nsarrOpt is String[] {
|
|
println("NSArray? is String[]")
|
|
} else {
|
|
println("NSArray? is not a String[]")
|
|
}
|
|
|
|
// CHECK-NEXT: NSArray! is String[]
|
|
if nsarrImplicitOpt is String[] {
|
|
println("NSArray! is String[]")
|
|
} else {
|
|
println("NSArray! is not a String[]")
|
|
}
|
|
|
|
// CHECK-NEXT: NSObject is String[]
|
|
if nsobj is String[] {
|
|
println("NSObject is String[]")
|
|
} else {
|
|
println("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[]
|
|
println("Forced to string array \(forcedStrArray)")
|
|
|
|
// CHECK-NEXT: Forced NSArray to string array [Hello, Swift, World]
|
|
forcedStrArray = nsarr as String[]
|
|
println("Forced NSArray to string array \(forcedStrArray)")
|
|
|
|
// CHECK-NEXT: Forced NSArray? to string array [Hello, Swift, World]
|
|
forcedStrArray = nsarrOpt as String[]
|
|
println("Forced NSArray? to string array \(forcedStrArray)")
|
|
|
|
// CHECK-NEXT: Forced NSArray! to string array [Hello, Swift, World]
|
|
forcedStrArray = nsarrImplicitOpt as String[]
|
|
println("Forced NSArray! to string array \(forcedStrArray)")
|
|
|
|
// CHECK-NEXT: Object-to-array cast produced [Hello, Swift, World]
|
|
if let strArr = obj as? NSString[] {
|
|
println("Object-to-array cast produced \(strArr)")
|
|
} else {
|
|
println("Object-to-array cast failed")
|
|
}
|
|
|
|
// CHECK-NEXT: Object-to-bridged-array cast failed due to bridge mismatch
|
|
if let strArr = obj as? Int[] {
|
|
println("Object-to-bridged-array cast should not have succedded")
|
|
} else {
|
|
println("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[] {
|
|
println("Array of strings should not be an array of ints!")
|
|
} else {
|
|
println("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 = ["Hello", "Swift", "World"] as String[]
|
|
if let strArr = objOpt as? String[] {
|
|
println("Object-to-bridged-array cast produced \(strArr)")
|
|
} else {
|
|
println("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[]
|
|
println("Forced to string array \(forcedStrArrayOpt)")
|
|
|
|
// CHECK-NEXT: Object-to-array cast produced [Hello, Swift, World]
|
|
if let strArr = objOpt as? NSString[] {
|
|
println("Object-to-array cast produced \(strArr)")
|
|
} else {
|
|
println("Object-to-array cast failed")
|
|
}
|
|
|
|
// CHECK: Object-to-bridged-array cast failed due to bridge mismatch
|
|
if let intArr = objOpt as? Int[] {
|
|
println("Object-to-bridged-array cast should not have succedded")
|
|
} else {
|
|
println("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[] {
|
|
println("Cast from nil succeeded?")
|
|
} else {
|
|
println("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 = ["Hello", "Swift", "World"] as String[]
|
|
if let strArr = objImplicitOpt as? String[] {
|
|
println("Object-to-bridged-array cast produced \(strArr)")
|
|
} else {
|
|
println("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[]
|
|
println("Forced to string array \(forcedStrArrayImplicitOpt)")
|
|
|
|
// CHECK-NEXT: Object-to-array cast produced [Hello, Swift, World]
|
|
if let strArr = objImplicitOpt as? NSString[] {
|
|
println("Object-to-array cast produced \(strArr)")
|
|
} else {
|
|
println("Object-to-array cast failed")
|
|
}
|
|
|
|
// CHECK: Object-to-bridged-array cast failed due to bridge mismatch
|
|
if let intArr = objImplicitOpt as? Int[] {
|
|
println("Object-to-bridged-array cast should not have succedded")
|
|
} else {
|
|
println("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[] {
|
|
println("Cast from nil succeeded?")
|
|
} else {
|
|
println("Object-to-bridged-array cast failed due to nil")
|
|
}
|
|
|
|
// Casting an array of numbers to different numbers.
|
|
// CHECK: Numbers-as-doubles cast produces [3.14159, 2.71828, 0.0]
|
|
obj = [3.14159, 2.71828, 0] as Double[]
|
|
if let doubleArr = obj as? Double[] {
|
|
println("Numbers-as-doubles cast produces \(doubleArr)")
|
|
} else {
|
|
println("Numbers-as-doubles failed")
|
|
}
|
|
|
|
// CHECK: Numbers-as-floats cast produces [3.14159{{.*}}, 2.71828{{.*}}, 0.0]
|
|
if let floatArr = obj as? Float[] {
|
|
println("Numbers-as-floats cast produces \(floatArr)")
|
|
} else {
|
|
println("Numbers-as-floats failed")
|
|
}
|
|
|
|
// CHECK: Numbers-as-ints cast produces [3, 2, 0]
|
|
if let intArr = obj as? Int[] {
|
|
println("Numbers-as-ints cast produces \(intArr)")
|
|
} else {
|
|
println("Numbers-as-ints failed")
|
|
}
|
|
|
|
// CHECK: Numbers-as-bools cast produces [true, true, false]
|
|
if let boolArr = obj as? Bool[] {
|
|
println("Numbers-as-bools cast produces \(boolArr)")
|
|
} else {
|
|
println("Numbers-as-bools failed")
|
|
}
|
|
|
|
println("ok") // CHECK: ok
|