mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Record the initializer type as soon as we have a solution, before it is applied, and get the type from the constriant system instead of from the final type checked expression. Note that the coerceToMaterializable() was unnecessary, since we always coerce the value to an rvalue type with coerceToType(). Eventually coerceToMaterializable() should go away. This is mostly NFC, except using the result of simplifyType() rather than the type of the final expression changes some diagnostics where it appears we were previously losing sugar. Also this accidentally fixes a crasher. Unfortunately the underlying issue is still there (applying a solution has bugs with opened existentials "leaking" out) -- this merely masks the problem by getting the initializer type directly from the constriant system.
172 lines
5.4 KiB
Swift
172 lines
5.4 KiB
Swift
// 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<Root, Root>()
|
|
var dictRO = Dictionary<Root, ObjC>()
|
|
var dictOR = Dictionary<ObjC, Root>()
|
|
var dictOO = Dictionary<ObjC, ObjC>()
|
|
var dictOD = Dictionary<ObjC, DerivesObjC>()
|
|
var dictDO = Dictionary<DerivesObjC, ObjC>()
|
|
var dictDD = Dictionary<DerivesObjC, DerivesObjC>()
|
|
|
|
var dictBB = Dictionary<BridgedToObjC, BridgedToObjC>()
|
|
var dictBO = Dictionary<BridgedToObjC, ObjC>()
|
|
var dictOB = Dictionary<ObjC, BridgedToObjC>()
|
|
|
|
// 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 '[BridgedToObjC : ObjC]' to type '[BridgedToObjC : BridgedToObjC]'}}
|
|
dictBB = dictOB // expected-error{{cannot assign value of type '[ObjC : BridgedToObjC]' to type '[BridgedToObjC : BridgedToObjC]'}}
|
|
|
|
dictDO = dictBB // expected-error{{cannot assign value of type '[BridgedToObjC : BridgedToObjC]' to type '[DerivesObjC : ObjC]'}}
|
|
dictOD = dictBB // expected-error{{cannot assign value of type '[BridgedToObjC : BridgedToObjC]' to type '[ObjC : DerivesObjC]'}}
|
|
dictDD = dictBB // expected-error{{cannot assign value of type '[BridgedToObjC : BridgedToObjC]' to type '[DerivesObjC : DerivesObjC]'}}
|
|
|
|
_ = dictDD; _ = dictDO; _ = dictOD; _ = dictOO; _ = dictOR; _ = dictOR; _ = dictRR; _ = dictRO
|
|
}
|
|
|
|
func testDowncastBridge() {
|
|
let dictRR = Dictionary<Root, Root>()
|
|
let dictRO = Dictionary<Root, ObjC>()
|
|
_ = Dictionary<ObjC, Root>()
|
|
_ = Dictionary<ObjC, ObjC>()
|
|
_ = Dictionary<ObjC, DerivesObjC>()
|
|
let dictDO = Dictionary<DerivesObjC, ObjC>()
|
|
_ = Dictionary<DerivesObjC, DerivesObjC>()
|
|
|
|
_ = Dictionary<BridgedToObjC, BridgedToObjC>()
|
|
let dictBO = Dictionary<BridgedToObjC, ObjC>()
|
|
let dictOB = Dictionary<ObjC, BridgedToObjC>()
|
|
|
|
// Downcast to bridged value types.
|
|
_ = dictRR as! Dictionary<BridgedToObjC, BridgedToObjC>
|
|
_ = dictRR as! Dictionary<BridgedToObjC, ObjC>
|
|
_ = dictRR as! Dictionary<ObjC, BridgedToObjC>
|
|
|
|
_ = dictRO as! Dictionary<BridgedToObjC, BridgedToObjC>
|
|
_ = dictRO as! Dictionary<BridgedToObjC, ObjC>
|
|
_ = dictRO as! Dictionary<ObjC, BridgedToObjC>
|
|
|
|
_ = dictBO as Dictionary<BridgedToObjC, BridgedToObjC>
|
|
_ = dictOB as Dictionary<BridgedToObjC, BridgedToObjC>
|
|
|
|
// We don't do mixed down/upcasts.
|
|
_ = dictDO as! Dictionary<BridgedToObjC, BridgedToObjC> // expected-warning{{forced cast from '[DerivesObjC : ObjC]' to 'Dictionary<BridgedToObjC, BridgedToObjC>' always succeeds; did you mean to use 'as'?}}
|
|
}
|
|
|
|
func testConditionalDowncastBridge() {
|
|
let dictRR = Dictionary<Root, Root>()
|
|
let dictRO = Dictionary<Root, ObjC>()
|
|
let dictOR = Dictionary<ObjC, Root>()
|
|
let dictOO = Dictionary<ObjC, ObjC>()
|
|
let dictOD = Dictionary<ObjC, DerivesObjC>()
|
|
let dictDO = Dictionary<DerivesObjC, ObjC>()
|
|
let dictDD = Dictionary<DerivesObjC, DerivesObjC>()
|
|
|
|
let dictBB = Dictionary<BridgedToObjC, BridgedToObjC>()
|
|
let dictBO = Dictionary<BridgedToObjC, ObjC>()
|
|
let dictOB = Dictionary<ObjC, BridgedToObjC>()
|
|
|
|
// Downcast to bridged value types.
|
|
if let d = dictRR as? Dictionary<BridgedToObjC, BridgedToObjC> { _ = d }
|
|
if let d = dictRR as? Dictionary<BridgedToObjC, ObjC> { _ = d }
|
|
if let d = dictRR as? Dictionary<ObjC, BridgedToObjC> { _ = d }
|
|
|
|
if let d = dictRO as? Dictionary<BridgedToObjC, BridgedToObjC> { _ = d }
|
|
if let d = dictRO as? Dictionary<BridgedToObjC, ObjC> { _ = d }
|
|
if let d = dictRO as? Dictionary<ObjC, BridgedToObjC> { _ = d }
|
|
|
|
let d1 = dictBO as Dictionary<BridgedToObjC, BridgedToObjC>
|
|
let d2 = dictOB as Dictionary<BridgedToObjC, BridgedToObjC>
|
|
|
|
// Mixed down/upcasts.
|
|
if let d = dictDO as? Dictionary<BridgedToObjC, BridgedToObjC> { _ = d }
|
|
// expected-warning@-1{{conditional cast from '[DerivesObjC : ObjC]' to 'Dictionary<BridgedToObjC, BridgedToObjC>' always succeeds}}
|
|
|
|
_ = dictRR
|
|
_ = dictRO
|
|
_ = dictOR
|
|
_ = dictOO
|
|
_ = dictOD
|
|
_ = dictDO
|
|
_ = dictDD
|
|
_ = dictBB
|
|
_ = dictBO
|
|
_ = dictOB
|
|
_ = d1
|
|
_ = d2
|
|
|
|
}
|
|
|
|
|
|
|
|
|