// Casts.swift - Tests for conversion between types. // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // // ----------------------------------------------------------------------------- /// /// Contains tests for non-trapping type conversions reported by users. /// // ----------------------------------------------------------------------------- // RUN: %empty-directory(%t) // // RUN: %target-build-swift -swift-version 5 -g -Onone -module-name a %s -o %t/a.swift5.Onone.out // RUN: %target-codesign %t/a.swift5.Onone.out // RUN: %target-run %t/a.swift5.Onone.out // // RUN: %target-build-swift -swift-version 5 -g -O -module-name a %s -o %t/a.swift5.O.out // RUN: %target-codesign %t/a.swift5.O.out // RUN: %target-run %t/a.swift5.O.out // // REQUIRES: executable_test // REQUIRES: concurrency // UNSUPPORTED: use_os_stdlib // UNSUPPORTED: back_deployment_runtime import StdlibUnittest #if _runtime(_ObjC) import Foundation #endif func blackhole(_ t: T) { } private func runtimeCast(_ from: T, to: U.Type) -> U? { return from as? U } let CastsTests = TestSuite("Casts") // Test for SR-426: missing release for some types after failed conversion CastsTests.test("No leak for failed tuple casts") { let t: Any = (1, LifetimeTracked(0)) expectFalse(t is Any.Type) } protocol P {} class ErrClass : Error { } CastsTests.test("No overrelease of existential boxes in failed casts") { // Test for crash from SR-392 // We fail casts of an existential box repeatedly // to ensure it does not get over-released. func bar(_ t: T) { for _ in 0..<10 { if case let a as P = t { _ = a } } } let err: Error = ErrClass() bar(err) } extension Int : P {} // Test for SR-7664: Inconsistent optional casting behaviour with generics // Runtime failed to unwrap multiple levels of Optional when casting. CastsTests.test("Multi-level optionals can be casted") { func testSuccess(_ x: From, from: From.Type, to: To.Type) { expectNotNil(x as? To) } func testFailure(_ x: From, from: From.Type, to: To.Type) { expectNil(x as? To) } testSuccess(42, from: Int?.self, to: Int.self) testSuccess(42, from: Int??.self, to: Int.self) testSuccess(42, from: Int???.self, to: Int.self) testSuccess(42, from: Int???.self, to: Int?.self) testSuccess(42, from: Int???.self, to: Int??.self) testSuccess(42, from: Int???.self, to: Int???.self) testFailure(42, from: Int?.self, to: String.self) testFailure(42, from: Int??.self, to: String.self) testFailure(42, from: Int???.self, to: String.self) } // Test for SR-9837: Optional.none not casting to Optional.none in generic context CastsTests.test("Optional.none can be casted to Optional.none in generic context") { func test(_ type: T.Type) -> T? { return Any?.none as? T } expectEqual(type(of: test(Bool.self)), Bool?.self) expectEqual(type(of: test(Bool?.self)), Bool??.self) } // Test for SR-3871: Cannot cast from ObjC existential without going through AnyObject #if _runtime(_ObjC) protocol P2 {} CastsTests.test("Cast from ObjC existential to Protocol (SR-3871)") { if #available(SwiftStdlib 5.3, *) { struct S: P2 {} class ObjCWrapper { @objc dynamic let any: Any = S() init() {} } let a = ObjCWrapper().any expectTrue(a is P2) // In SR-3871, the following cast failed (everything else here succeeded) expectNotNil(a as? P2) expectNotNil(a as? S) let b = a as AnyObject expectTrue(a is P2) expectNotNil(b as? P2) expectNotNil(b as? S) } } #endif protocol P3 {} CastsTests.test("Cast from Swift existential to Protocol") { struct S: P3 {} class SwiftWrapper { let any: Any = S() init() {} } let a = SwiftWrapper().any expectTrue(a is P3) expectNotNil(a as? P3) expectNotNil(a as? S) let b = a as AnyObject expectTrue(b is P3) expectNotNil(b as? P3) expectNotNil(b as? S) } #if _runtime(_ObjC) extension CFBitVector : P { static func makeImmutable(from values: Array) -> CFBitVector { return CFBitVectorCreate(/*allocator:*/ nil, values, values.count * 8) } } extension CFMutableBitVector { static func makeMutable(from values: Array) -> CFMutableBitVector { return CFBitVectorCreateMutableCopy( /*allocator:*/ nil, /*capacity:*/ 0, CFBitVector.makeImmutable(from: values)) } } func isP(_ t: T) -> Bool { return t is P } CastsTests.test("Dynamic casts of CF types to protocol existentials (SR-2289)") .skip(.custom({ !_isDebugAssertConfiguration() }, reason: "This test behaves unpredictably in optimized mode.")) .code { expectTrue(isP(10 as Int)) if #available(SwiftStdlib 5.5, *) { expectTrue(isP(CFBitVector.makeImmutable(from: [10, 20]))) expectTrue(isP(CFMutableBitVector.makeMutable(from: [10, 20]))) } } #endif // Another test for SR-3871, SR-5590, SR-6309, SR-8651: // user type in a _SwiftValue in an Optional can't be cast to a protocol. // Note: This uses the (misnamed) _bridgeAnythingToObjectiveC so it can // test these paths on Linux as well. protocol P6309 {} CastsTests.test("Casting struct -> Obj-C -> Protocol fails (SR-3871, SR-5590, SR-6309, SR-8651)") { struct S: P6309 { let value: Int let tracker = LifetimeTracked(13) } let a: P6309 = S(value: 13) let b = _bridgeAnythingToObjectiveC(a) let d = b as? Any let e = d as? P6309 expectNotNil(e) } protocol P4552 {} if #available(SwiftStdlib 5.5, *) { CastsTests.test("Casting Any(Optional(T)) -> Protocol fails (SR-4552)") { struct S: P4552 { let tracker = LifetimeTracked(13) } let a = S() let b: S? = a let c = b as? Any let d = c as? P4552 expectNotNil(d) } } // rdar://27108240 (Optional casting bug (crash)) protocol Key { associatedtype Value } CastsTests.test("Cast to associated type") { // Helper function to bypass compiler cast optimizations func runtimeCast (_ x: From, to: To.Type) -> To? { return x as? To } struct StringKey : Key { typealias Value = String? } var string: String? func value(forKey key: K.Type) { let b = runtimeCast(string, to: K.Value.self) expectNotNil(b) let c = string as? K.Value expectNotNil(c) } value(forKey: StringKey.self) } #if _runtime(_ObjC) // rdar://36288786 (Swift metatype stored in an Objective-C id property can't be typecast back to its original type) CastsTests.test("Store Swift metatype in ObjC property and cast back to Any.Type") { class MyObj { var sVar: Any? = nil @objc dynamic var objcVar: Any? = nil } let a = MyObj() // Double values a.sVar = 1.234 a.objcVar = 1.234 let sValue1 = a.sVar as? Double let objcValue1 = a.objcVar as? Double expectEqual(sValue1, objcValue1) // Swift types let b = Bool.self a.sVar = b a.objcVar = b let sValue2 = a.sVar as? Any.Type let objcValue2 = a.objcVar as? Any.Type expectTrue(sValue2 == b) if #available(SwiftStdlib 5.5, *) { expectTrue(sValue2 == objcValue2) expectTrue(objcValue2 == b) } } #endif // rdar://37793004 ([dynamic casting] [SR-7049]: Enums don't cast back from AnyHashable) CastsTests.test("Enums don't cast back from AnyHashable (SR-7049)") { enum E { case a } // This works as expected. let str: AnyHashable = "hello" expectNotNil(str as? String) // Optional("hello") expectNotNil(str as? String as Any) // Optional("hello") // This doesn't. let ea: AnyHashable = E.a expectNotNil(ea as? E) expectNotNil(ea as? E as Any) expectEqual((ea as? E), E.a) } #if _runtime(_ObjC) //rdar://39415812 ([dynamic casting] [SR-7432]: Can't see through boxed _SwiftValue when casting from @objc Type) @objc(Exporter) protocol Exporter: NSObjectProtocol { var type: Any { get } func export(item: Any) -> String? } CastsTests.test("Casts from @objc Type") { struct User { var name: String } final class UserExporter: NSObject, Exporter { var type: Any { return User.self } func export(item: Any) -> String? { let u = item as? User return u?.name } } let user = User(name: "Kermit") let exporter: Exporter = UserExporter() if #available(SwiftStdlib 5.5, *) { expectTrue(exporter.type is User.Type) } expectNotNil(exporter.export(item: user)) } #endif #if _runtime(_ObjC) // rdar://44467533 (Swift main branch: conditional casts for _ObjectiveCBridgeable miscompile in swift-corelibs-foundation) CastsTests.test("Conditional NSNumber -> Bool casts") { let x = NSNumber(value: -1) as? Bool expectNil(x) } #endif // rdar://45217461 ([dynamic casting] [SR-8964]: Type check operator (is) fails for Any! variable holding an Error (struct) value) if #available(SwiftStdlib 5.5, *) { CastsTests.test("Casts from Any(struct) to Error (SR-8964)") { struct MyError: Error { } let a: Any! = MyError() let b: Any = a expectTrue(b is Error) } } #if _runtime(_ObjC) // rdar://15494623 (Handle dynamic cast to archetype bound to ObjC existential) CastsTests.test("Dynamic cast to ObjC protocol") { func genericCast(x: NSObject, _: T.Type) -> T? { return x as? T } let n: NSNumber = 1 let copying = genericCast(x: n, NSCopying.self) expectNotNil(copying) } #endif // SR-6126 if #available(macOS 11.3, iOS 14.5, tvOS 14.5, watchOS 7.4, *) { CastsTests.test("Nil handling for Optionals and Arrays (SR-6126)") { func check(_ arg: Int??) -> String { switch arg { case .none: return ".none" case .some(.none): return ".some(.none)" case .some(.some): return ".some(.some)" } } let x: Int? = .none let y: [Int?] = [.none] let a = x as Int?? let b = (x as? Int??)! let b2 = runtimeCast(x, to: Int??.self)! let c = Int?.none as Int?? let d = (Int?.none as? Int??)! let d2 = runtimeCast(Int?.none, to: Int??.self)! let e = (y as [Int??]).first! let f = (y as? [Int??])!.first! let f2 = runtimeCast(y, to: [Int??].self)!.first! let g = ([Int?.none] as [Int??]).first! let h = ([Int?.none] as? [Int??])!.first! let h2 = runtimeCast([Int?.none], to: [Int??].self)!.first! // Original reporter believes all of these should be .some(.none) expectEqual(".some(.none)", check(a)) // Xcode 9.0: .some(.none) expectEqual(".some(.none)", check(b)) // Xcode 9.0: .some(.none) expectEqual(".some(.none)", check(b2)) expectEqual(".some(.none)", check(c)) // Xcode 9.0: .some(.none) expectEqual(".some(.none)", check(d)) // Xcode 9.0: .some(.none) expectEqual(".some(.none)", check(d2)) expectEqual(".some(.none)", check(e)) // Xcode 9.0: .none expectEqual(".some(.none)", check(f)) // Xcode 9.0: .none expectEqual(".some(.none)", check(f2)) expectEqual(".some(.none)", check(g)) // Xcode 9.0: .some(.none) expectEqual(".some(.none)", check(h)) // Xcode 9.0: .none expectEqual(".some(.none)", check(h2)) } } protocol SwiftProtocol {} CastsTests.test("Swift Protocol Metatypes don't self-conform") { let a = SwiftProtocol.self // `is P.Protocol` tests whether the argument is a subtype of P. // In particular, the protocol identifier `P.self` is such a subtype. if #available(SwiftStdlib 5.5, *) { expectNotNil(runtimeCast(a, to: SwiftProtocol.Protocol.self)) // Fixed by rdar://58991956 } expectNotNil(a as? SwiftProtocol.Protocol) expectTrue(a is SwiftProtocol.Protocol) blackhole(a as! SwiftProtocol.Protocol) // Should not trap // `is P.Type` tests conformance to P. Protocols cannot conform to // protocols, so these always fail. expectNil(runtimeCast(a, to: SwiftProtocol.Type.self)) expectNil(a as? SwiftProtocol.Type) expectFalse(a is SwiftProtocol.Type) } CastsTests.test("Self-conformance for Any.self") { let b = Any.self expectNotNil(runtimeCast(b, to: Any.Protocol.self)) blackhole(b as! Any.Protocol) // Should not trap expectTrue(b is Any.Protocol) expectNotNil(b as? Any.Protocol) // Unlike most other protocols, Any.self does conform to Any expectNotNil(runtimeCast(b, to: Any.Type.self)) expectNotNil(b as? Any.Type) expectTrue(b is Any.Type) blackhole(b as! Any.Type) } // rdar://59067748 (Error Protocol should self-conform in optimized casts) CastsTests.test("Self-conformance for Error.self") .skip(.custom({ !_isDebugAssertConfiguration() }, reason: "Cast optimizer breaks this test")) .code { let c = Error.self expectNotNil(runtimeCast(c, to: Error.Protocol.self)) expectNotNil(c as? Error.Protocol) expectTrue(c is Error.Protocol) blackhole(c as! Error.Protocol) // Unlike most other protocols, Error.self does conform to Error expectNotNil(runtimeCast(c, to: Error.Type.self)) expectFailure { expectNotNil(c as? Error.Type) } expectFailure { expectTrue(c is Error.Type) } // blackhole(c as! Error.Type) // Should not trap, but currently does } // rdar://59067556 (Obj-C Protocol Metatypes should self-conform) #if _runtime(_ObjC) @objc protocol ObjCProtocol {} CastsTests.test("ObjC Protocol Metatypes self-conform") { let a = ObjCProtocol.self if #available(SwiftStdlib 5.5, *) { expectNotNil(runtimeCast(a, to: ObjCProtocol.Protocol.self)) } expectNotNil(a as? ObjCProtocol.Protocol) expectTrue(a is ObjCProtocol.Protocol) blackhole(a as! ObjCProtocol.Protocol) // Unlike Swift protocols, ObjC protocols do conform to themselves expectFailure { expectNotNil(runtimeCast(a, to: ObjCProtocol.Type.self)) } expectFailure { expectNotNil(a as? ObjCProtocol.Type) } expectFailure { expectTrue(a is ObjCProtocol.Type) } // blackhole(a as! ObjCProtocol.Type) // Should not trap, but currently does } #endif #if _runtime(_ObjC) protocol NewStringProtocol {} extension String: NewStringProtocol { } CastsTests.test("String/NSString extension compat") { let x: Any = NSString() expectFailure { expectNotNil(runtimeCast(x, to: NewStringProtocol.self)) } expectFailure { expectNotNil(x as? NewStringProtocol) } } #endif protocol P1999 {} if #available(SwiftStdlib 5.5, *) { CastsTests.test("Cast Any(Optional(class)) to Protocol type (SR-1999)") { class Foo: P1999 { } let optionalFoo : Foo? = Foo() let anyValue: Any = optionalFoo let foo1 = anyValue as? Foo expectNotNil(foo1) let foo2 = anyValue as? P1999 expectNotNil(foo2) let foo3 = runtimeCast(anyValue, to: Foo.self) expectNotNil(foo3) let foo4 = runtimeCast(anyValue, to: P1999.self) expectNotNil(foo4) } } #if _runtime(_ObjC) CastsTests.test("Dict value casting (SR-2911)") { var dict: [AnyHashable: String] = [:] dict["Key"] = "Value" expectNotNil(dict["Key"] as? NSString) expectNotNil(runtimeCast(dict["Key"], to: NSString.self)) } #endif #if _runtime(_ObjC) CastsTests.test("String coercions should work on Linux (SR-12020)") { let a = "abc" as Substring as NSString let b = "abc" as NSString expectEqual(a, b) let c = "abc" as Substring let d = c as? NSString let e = "abc" as? NSString expectEqual(d, e) let f = runtimeCast(d, to: NSString.self) expectEqual(e, f) } #endif class ClassInt: Equatable, Hashable { private var tracker = LifetimeTracked(77) static func == (lhs: ClassInt, rhs: ClassInt) -> Bool {return true} func hash(into hasher: inout Hasher) {} } CastsTests.test("AnyHashable(Class) -> Obj-C -> Class") { let a = ClassInt() let b = runtimeCast(a, to: AnyHashable.self)! let c = _bridgeAnythingToObjectiveC(b) let d = /* SwiftValueBox(AnyHashable(ClassInt)) */ c as? ClassInt expectNotNil(d) let d2 = runtimeCast(c, to: ClassInt.self) expectNotNil(d2) let e = runtimeCast(/* SwiftValueBox(AnyHashable(ClassInt)) */ c, to: ClassInt.self) expectNotNil(e) } #if _runtime(_ObjC) // rdar://58999120 CastsTests.test("Error -> NSError -> Protocol transitivity (SR-12095)") { enum NonConformingError: Error { case ok } let nonConformingError: Error = NonConformingError.ok // NSError conforms to CustomStringConvertible, so ... let conformingError = nonConformingError as? NSError expectTrue(conformingError is CustomStringConvertible) expectNotNil(conformingError as? CustomStringConvertible) // Our error type does not conform directly, but should conform // indirectly because of NSError... // Note: Known broken in both runtime and compiler. expectFailure { expectTrue(nonConformingError is CustomStringConvertible) } expectFailure { expectNotNil(nonConformingError as? CustomStringConvertible) } } #endif #if _runtime(_ObjC) CastsTests.test("Runtime crash casting Obj-C object to Obj-C protocol (rdar://16449805)") { // FIXME: The reported crash was for `NSPoint(x:0, y:0) as? NSCoding`, // but NSPoint seems to not be available on 32-bit platforms. expectNotNil(NSString() as? NSCoding) } #endif CastsTests.test("Casting Swift Error-conforming types to Error existentials") { enum Foo: Error { case OK case Broken } let a = Foo.Broken let b = a as? Error expectNotNil(b) let c = b as? Foo expectNotNil(c) let d = Foo.self as? Error.Type expectNotNil(d) } #if _runtime(_ObjC) CastsTests.test("Casting NSError <-> Error") { @objc class Bar: NSError { init() {super.init(domain: "Bar", code: 99)} required init?(coder: NSCoder) {super.init(coder: coder)} } let e = Bar.self as? Error.Type expectNotNil(e) let f = Bar.self as? Bar.Type expectNotNil(f) let g = Bar() as? Error expectNotNil(g) } #endif // Foundation's JSON handling makes heavy use of passing Any? inside of Any // existentials. That inspired the following three checks: CastsTests.test("[Any(Any?)] -> [Any?] should prefer unwrapping source") { let a: Any? = nil let b: [Any] = [a as Any] let c = b as? [Any?] let d = c! let e = d[0] expectNil(e) } CastsTests.test("Any(Any?) -> Any? should prefer unwrapping source") { let a: Any? = nil let b: Any = a let c = b as? Any? let d = c! expectNil(d) } #if _runtime(_ObjC) CastsTests.test("NSNull?.none -> Any? should set outer nil") { let a: NSNull? = nil let b = a as? Any? let c = b! expectNil(c) } #endif if #available(macOS 11.3, iOS 14.5, tvOS 14.5, watchOS 7.4, *) { CastsTests.test("Int??.some(nil) => Int??? should inject naturally") { let a: Int?? = .some(nil) let b = a as? Int??? let c = b! let d = c! let e = d! expectNil(e) } } if #available(macOS 11.3, iOS 14.5, tvOS 14.5, watchOS 7.4, *) { CastsTests.test("Int??.some(nil) => String??? should inject naturally") { let a: Int?? = .some(nil) let b = runtimeCast(a, to: String???.self) let c = b! let d = c! let e = d! expectNil(e) } } if #available(macOS 11.3, iOS 14.5, tvOS 14.5, watchOS 7.4, *) { CastsTests.test("Int??.some(nil) => Any??? should inject naturally") { let a: Int?? = .some(nil) let b = a as? Any??? let c = b! let d = c! let e = d! expectNil(e) } } #if _runtime(_ObjC) CastsTests.test("NSString -> String fast path") { let a = "short" as NSString expectNotNil(a as? String) let b = runtimeCast(a, to: String.self) expectNotNil(b) let c = "Long (adj) -- extended, large, the opposite of short" as NSString expectNotNil(c as? String) let d = runtimeCast(c, to: String.self) expectNotNil(d) let e = NSMutableString("not read-only") expectNotNil(e as? String) let f = runtimeCast(e, to: String.self) expectNotNil(f) let g = CFStringCreateWithCString(nil, "hello, world", CFStringBuiltInEncodings.UTF8.rawValue) expectNotNil(g as? String) let h = runtimeCast(g, to: String.self) expectNotNil(h) let i = CFStringCreateMutable(nil, 0) expectNotNil(i as? String) let j = runtimeCast(i, to: String.self) expectNotNil(j) } #endif // This fails in optimized builds because after inlining `runtimeCast`, // the resulting SIL cast operation is left in a form that IRGen can't // correctly handle. //CastsTests.test("Optimized metatype -> AnyObject cast") { // struct StructInt { } // let a = StructInt.self // let b = runtimeCast(a, to: AnyObject.self) // expectNotNil(b) //} CastsTests.test("Any.Protocol") { class C {} struct S {} func isAnyProtocol(_ type: T.Type) -> Bool { let result = T.self is Any.Protocol if result { // `as!` should succeed if `is` does blackhole(T.self as! Any.Protocol) } return result } func isAnyType(_ type: T.Type) -> Bool { return T.self is Any.Type } func isType(_ type: T.Type, to: U.Type) -> Bool { return T.self is U.Type } expectTrue(Int.self is Any.Type) expectNotNil(Int.self as? Any.Type) expectTrue(isAnyType(Int.self)) expectFalse(Int.self is Any.Protocol) expectNil(Int.self as? Any.Protocol) expectFalse(isAnyProtocol(Int.self)) expectFalse(isType(Int.self, to: Any.self)) expectTrue(C.self is Any.Type) expectNotNil(C.self as? Any.Type) expectTrue(isAnyType(C.self)) expectFalse(C.self is Any.Protocol) expectNil(C.self as? Any.Protocol) expectFalse(isAnyProtocol(C.self)) expectFalse(isType(C.self, to: Any.self)) expectTrue(S.self is Any.Type) expectNotNil(S.self as? Any.Type) expectTrue(isAnyType(S.self)) expectFalse(S.self is Any.Protocol) expectNil(S.self as? Any.Protocol) expectFalse(isAnyProtocol(S.self)) expectFalse(isType(S.self, to: Any.self)) expectTrue(Any.self is Any.Type) expectNotNil(Any.self as? Any.Type) expectTrue(isAnyType(Any.self)) expectTrue(Any.self is Any.Protocol) expectNotNil(Any.self as? Any.Protocol) expectTrue(isAnyProtocol(Any.self)) expectTrue(isType(Any.self, to: Any.self)) expectTrue(Any?.self is Any.Type) expectNotNil(Any?.self as? Any.Type) expectTrue(isAnyType(Any?.self)) expectFalse(Any?.self is Any.Protocol) expectNil(Any?.self as? Any.Protocol) expectFalse(isAnyProtocol(Any?.self)) expectFalse(isType(Any?.self, to: Any.self)) } CastsTests.test("Async function types") { let asyncFnType: Any.Type = (() async -> Void).self let fnType: Any.Type = (() -> Void).self expectTrue(fnType is (() -> Void).Type) expectTrue(asyncFnType is (() async -> Void).Type) expectFalse(fnType is (() async -> Void).Type) expectFalse(asyncFnType is (() -> Void).Type) } // `Optional` is Hashable, so it must cast to AnyHashable, // even if it contains a nil. (This was broken in 5.3 and earlier, // but was fixed by the new dynamic cast runtime.) CastsTests.test("Optional nil -> AnyHashable") { let a : Int? = nil expectNotNil(a as? AnyHashable) } #if _runtime(_ObjC) // See below for notes about missing Linux functionality // that prevents us from running this test there. CastsTests.test("AnyObject.Type -> AnyObject") { class C {} let a = C.self let b = a as? AnyObject.Type expectNotNil(b) // Note: On macOS, the following cast generates a call to // `swift_dynamicCastMetatypeToObjectConditional` That function is currently // unimplemented on Linux, so this cast always fails on Linux. let c = b as? AnyObject expectNotNil(c) // Note: The following cast currently succeeds on Linux only by stuffing the // source into a `__SwiftValue` container, which breaks the checks below. let d = runtimeCast(b, to: AnyObject.self) expectNotNil(d) let e = c as? C.Type expectNotNil(e) let f = runtimeCast(d, to: C.Type.self) expectNotNil(f) // Verify that the round-trip casts yield exactly the same pointer. In // particular, none of the casts above should fall back on stuffing the source // into a `__SwiftValue` container. expectTrue(c! === a) expectTrue(d! === a) expectTrue(e! === a) expectTrue(f! === a) } #endif protocol Fruit {} CastsTests.test("Generic type validation [SR-13812]") { func check(a: A.Type, b: B.Type) -> Bool { return (a is B.Type) } struct Apple: Fruit {} expectFalse(check(a: Apple.self, b: Fruit.self)) expectFalse(Apple.self is Fruit.Protocol) expectTrue(Apple.self is Fruit.Type) } CastsTests.test("Cast failure for Any! holding Error struct [SR-8964]") { struct MyError: Error {} let a: Any! = MyError() let b: Any = a expectTrue(b is Error) } CastsTests.test("Cannot cast from Any? to Existential [SR-1999]") { let a = Float(1) as Any as? Float expectNotNil(a) let b = Float(1) as Any as? CustomStringConvertible expectNotNil(b) let c = Optional.some(Float(1)) as Any as? Float expectNotNil(c) let d = Optional.some(Float(1)) as Any as? CustomStringConvertible expectNotNil(d) } protocol A {} CastsTests.test("Failing cast from Any to Optional [SR-6279]") { struct B: A {} // If we have an optional instance, stored as an `Any` let b: A? = B() let c = b as Any // This fails to cast, should succeed. let d = c as? A expectNotNil(d) // There is a workaround, but not ideal. func cast(_ t: T, to: U.Type) -> U? { return t as? U } let f = cast(c, to: Any?.self) as? A expectNotNil(f) } protocol SuperProtocol{} CastsTests.test("Casting Objects retained from KeyPaths to Protocols is not working properly") { // This is the simplified reproduction from rdar://59844232 which doesn't // actually use KeyPaths class SubClass : SuperProtocol{} let value = SubClass() as Any? as Any expectNotNil(value as? SubClass) expectNotNil(value as? SuperProtocol) } #if _runtime(_ObjC) // Known to still be broken, but we can document the issue here public protocol SomeProtocol {} extension NSString: SomeProtocol {} CastsTests.test("NSDictionary -> Dictionary casting [SR-12025]") { // Create NSDictionary with one entry var a = NSMutableDictionary() a[NSString("key")] = NSString("value") let v = NSString("value") let v2 = v as? SomeProtocol expectNotNil(v2) // Test casting of the dictionary let b = a as? [String:SomeProtocol] expectFailure { expectNotNil(b) } // Expect non-nil, but see nil let c = a as? [String:Any] expectNotNil(c) // Non-nil (as expected) let d = c as? [String:SomeProtocol] expectNotNil(d) // Non-nil (as expected) } #endif // Casting optionals to AnyHashable is a little peculiar // TODO: It would be nice if AnyHashable(Optional("Foo")) == AnyHashable("Foo") // (including as dictionary keys). That would make this a lot less confusing. CastsTests.test("Optional cast to AnyHashable") { let d: [String?: String] = ["FooKey": "FooValue", nil: "NilValue"] // In Swift 5.3, this cast DOES unwrap the non-nil key // We've deliberately tried to preserve that behavior in Swift 5.4 let d2 = d as [AnyHashable: String] // After SR-9047, all four of the following should work: let d3 = d2["FooKey" as String? as AnyHashable] expectNil(d3) let d4 = d2["FooKey" as String?] expectNil(d4) let d5 = d2["FooKey"] expectNotNil(d5) let d6 = d2["FooKey" as AnyHashable] expectNotNil(d6) // The nil key should be preserved and still function let d7 = d2[String?.none as AnyHashable] expectNotNil(d7) // Direct casts via the runtime unwrap the optional let a: String = "Foo" let ah: AnyHashable = a let b: String? = a let bh = runtimeCast(b, to: AnyHashable.self) expectEqual(bh, ah) // Direct casts that don't go through the runtime don't unwrap the optional // This is inconsistent with the runtime cast behavior above. We should // probably change the runtime behavior above to work the same as this, // but that should wait until SR-9047 lands. let x: String = "Baz" let xh = x as AnyHashable let y: String? = x let yh = y as AnyHashable // Doesn't unwrap the optional // xh is AnyHashable("Baz") // yh is AnyHashable(Optional("Baz")) expectNotEqual(xh, yh) } // Repeatedly casting to AnyHashable should still test equal. // (This was broken for a while because repeatedly casting to // AnyHashable could end up with multiple nested AnyHashables.) // rdar://75180619 CastsTests.test("Recursive AnyHashable") { struct P: Hashable { var x: Int } struct S { var x: AnyHashable? init(_ x: T?) { self.x = x } } let p = P(x: 0) let hp = p as AnyHashable? print(hp.debugDescription) let s = S(hp) print(s.x.debugDescription) expectEqual(s.x, hp) expectEqual(s.x, p) } // SR-14635 (aka rdar://78224322) #if _runtime(_ObjC) CastsTests.test("Do not overuse __SwiftValue") .skip(.osxAny("SR-14635 not yet fully enabled for Apple OSes")) .skip(.iOSAny("SR-14635 not yet fully enabled for Apple OSes")) .skip(.iOSSimulatorAny("SR-14635 not yet fully enabled for Apple OSes")) .skip(.tvOSAny("SR-14635 not yet fully enabled for Apple OSes")) .skip(.tvOSSimulatorAny("SR-14635 not yet fully enabled for Apple OSes")) .skip(.watchOSAny("SR-14635 not yet fully enabled for Apple OSes")) .skip(.watchOSSimulatorAny("SR-14635 not yet fully enabled for Apple OSes")) .code { struct Bar {} // This used to succeed because of overeager __SwiftValue // boxing (and __SwiftValue does satisfy NSCopying) expectFalse(Bar() is NSCopying) expectFalse(Bar() as Any is NSCopying) // This seems unavoidable? // `Bar() as! AnyObject` gets boxed as a __SwiftValue, // and __SwiftValue does conform to NSCopying expectTrue(Bar() as! AnyObject is NSCopying) class Foo {} // Foo does not conform to NSCopying // (This used to succeed due to over-eager __SwiftValue boxing) expectFalse(Foo() is NSCopying) expectFalse(Foo() as Any is NSCopying) // A type that really does conform should cast to NSCopying class Foo2: NSCopying { func copy(with: NSZone?) -> Any { return self } } expectTrue(Foo2() is NSCopying) expectTrue(Foo2() is AnyObject) } #endif #if _runtime(_ObjC) CastsTests.test("Artificial subclass protocol conformance") { class SwiftClass: NSObject {} let subclass: AnyClass = objc_allocateClassPair(SwiftClass.self, "ArtificialSwiftSubclass", 0)! objc_registerClassPair(subclass) expectFalse(subclass is P.Type) } #endif CastsTests.test("Do not overuse __SwiftValue (non-ObjC)") { struct Bar {} // This should succeed because this is what __SwiftValue boxing is for expectTrue(Bar() is AnyObject) expectTrue(Bar() as Any is AnyObject) class Foo {} // Any class type can be cast to AnyObject expectTrue(Foo() is AnyObject) } runAllTests()