// RUN: %target-typecheck-verify-swift // REQUIRES: objc_interop // FIXME: Should go into the standard library. public extension _ObjectiveCBridgeable { static func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectiveCType?) -> Self { var result: Self? _forceBridgeFromObjectiveC(source!, result: &result) return result! } } class Root : Hashable { var hashValue: Int { return 0 } } func ==(x: Root, y: Root) -> Bool { return true } class ObjC : Root { var x = 0 } class DerivesObjC : ObjC { } struct BridgedToObjC : Hashable, _ObjectiveCBridgeable { func _bridgeToObjectiveC() -> ObjC { return ObjC() } static func _forceBridgeFromObjectiveC( _ x: ObjC, result: inout BridgedToObjC? ) { } static func _conditionallyBridgeFromObjectiveC( _ x: ObjC, result: inout BridgedToObjC? ) -> Bool { return true } var hashValue: Int { return 0 } } func ==(x: BridgedToObjC, y: BridgedToObjC) -> Bool { return true } func testUpcastBridge() { var dictRR = Dictionary() var dictRO = Dictionary() var dictOR = Dictionary() var dictOO = Dictionary() var dictOD = Dictionary() var dictDO = Dictionary() var dictDD = Dictionary() var dictBB = Dictionary() var dictBO = Dictionary() var dictOB = Dictionary() // Upcast to object types. dictRR = dictBB as [Root: Root] dictRR = dictBO as [Root: Root] dictRR = dictOB as [Root: Root] dictRO = dictBB as [Root: ObjC] dictRO = dictBO as [Root: ObjC] dictRO = dictOB as [Root: ObjC] dictOR = dictBB as [ObjC: Root] dictOR = dictBO as [ObjC: Root] dictOR = dictOB as [ObjC: Root] dictOO = dictBB as [ObjC: ObjC] dictOO = dictBO as [ObjC: ObjC] dictOO = dictOB as [ObjC: ObjC] // Upcast key or value to object type (but not both) dictBO = dictBB as [BridgedToObjC: ObjC] dictOB = dictBB as [ObjC: BridgedToObjC] dictBB = dictBO // expected-error{{cannot assign value of type 'Dictionary' to type 'Dictionary'}} dictBB = dictOB // expected-error{{cannot assign value of type 'Dictionary' to type 'Dictionary'}} dictDO = dictBB // expected-error{{cannot assign value of type 'Dictionary' to type 'Dictionary'}} dictOD = dictBB // expected-error{{cannot assign value of type 'Dictionary' to type 'Dictionary'}} dictDD = dictBB // expected-error{{cannot assign value of type 'Dictionary' to type 'Dictionary'}} _ = dictDD; _ = dictDO; _ = dictOD; _ = dictOO; _ = dictOR; _ = dictOR; _ = dictRR; _ = dictRO } func testDowncastBridge() { let dictRR = Dictionary() let dictRO = Dictionary() _ = Dictionary() _ = Dictionary() _ = Dictionary() let dictDO = Dictionary() _ = Dictionary() _ = Dictionary() let dictBO = Dictionary() let dictOB = Dictionary() // Downcast to bridged value types. _ = dictRR as! Dictionary _ = dictRR as! Dictionary _ = dictRR as! Dictionary _ = dictRO as! Dictionary _ = dictRO as! Dictionary _ = dictRO as! Dictionary _ = dictBO as Dictionary _ = dictOB as Dictionary // We don't do mixed down/upcasts. _ = dictDO as! Dictionary // expected-warning{{forced cast from 'Dictionary' to 'Dictionary' always succeeds; did you mean to use 'as'?}} } func testConditionalDowncastBridge() { let dictRR = Dictionary() let dictRO = Dictionary() let dictOR = Dictionary() let dictOO = Dictionary() let dictOD = Dictionary() let dictDO = Dictionary() let dictDD = Dictionary() let dictBB = Dictionary() let dictBO = Dictionary() let dictOB = Dictionary() // Downcast to bridged value types. if let d = dictRR as? Dictionary { _ = d } if let d = dictRR as? Dictionary { _ = d } if let d = dictRR as? Dictionary { _ = d } if let d = dictRO as? Dictionary { _ = d } if let d = dictRO as? Dictionary { _ = d } if let d = dictRO as? Dictionary { _ = d } let d1 = dictBO as Dictionary let d2 = dictOB as Dictionary // Mixed down/upcasts. if let d = dictDO as? Dictionary { _ = d } // expected-warning@-1{{conditional cast from 'Dictionary' to 'Dictionary' always succeeds}} _ = dictRR _ = dictRO _ = dictOR _ = dictOO _ = dictOD _ = dictDO _ = dictDD _ = dictBB _ = dictBO _ = dictOB _ = d1 _ = d2 }