mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
This way it covers a lot more ground and doesn't conflict with
other fixes.
Another notable change is related to check for IUO associated
with source type, that covers cases like:
```swift
func foo(_ v: NSString!) -> String {
return v
}
```
Instead of general conversion failure check for IUO enables solver
to introduce force downcast fix.
176 lines
6.3 KiB
Swift
176 lines
6.3 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 {
|
|
func hash(into hasher: inout Hasher) {}
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
func hash(into hasher: inout Hasher) {}
|
|
}
|
|
|
|
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]'}}
|
|
// expected-note@-1 {{arguments to generic parameter 'Value' ('ObjC' and 'BridgedToObjC') are expected to be equal}}
|
|
dictBB = dictOB // expected-error{{cannot assign value of type '[ObjC : BridgedToObjC]' to type '[BridgedToObjC : BridgedToObjC]'}}
|
|
// expected-note@-1 {{arguments to generic parameter 'Key' ('ObjC' and 'BridgedToObjC') are expected to be equal}}
|
|
|
|
dictDO = dictBB // expected-error{{cannot assign value of type '[BridgedToObjC : BridgedToObjC]' to type '[DerivesObjC : ObjC]'}}
|
|
//expected-note@-1 {{arguments to generic parameter 'Key' ('BridgedToObjC' and 'DerivesObjC') are expected to be equal}}
|
|
//expected-note@-2 {{arguments to generic parameter 'Value' ('BridgedToObjC' and 'ObjC') are expected to be equal}}
|
|
dictOD = dictBB // expected-error {{cannot assign value of type '[BridgedToObjC : BridgedToObjC]' to type '[ObjC : DerivesObjC]'}}
|
|
//expected-note@-1 {{arguments to generic parameter 'Key' ('BridgedToObjC' and 'ObjC') are expected to be equal}}
|
|
//expected-note@-2 {{arguments to generic parameter 'Value' ('BridgedToObjC' and 'DerivesObjC') are expected to be equal}}
|
|
dictDD = dictBB // expected-error {{cannot assign value of type '[BridgedToObjC : BridgedToObjC]' to type '[DerivesObjC : DerivesObjC]'}}
|
|
//expected-note@-1 {{arguments to generic parameter 'Key' ('BridgedToObjC' and 'DerivesObjC') are expected to be equal}}
|
|
//expected-note@-2 {{arguments to generic parameter 'Value' ('BridgedToObjC' and 'DerivesObjC') are expected to be equal}}
|
|
|
|
_ = 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
|
|
|
|
}
|
|
|
|
|
|
|
|
|