mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
SR-0140: Bridge Optionals to nonnull ObjC objects by bridging their payload, or using a sentinel.
id-as-Any lets you pass Optional to an ObjC API that takes `nonnull id`, and also lets you bridge containers of `Optional` to `NSArray` etc. When this occurs, we can unwrap the value and bridge it so that inhabited optionals still pass into ObjC in the expected way, but we need something to represent `none` other than the `nil` pointer. Cocoa provides `NSNull` as the canonical "null for containers" object, which is the least bad of many possible answers. If we happen to have the rare nested optional `T??`, there is no precedented analog for these in Cocoa, so just generate a unique sentinel object to preserve the `nil`-ness depth so we at least don't lose information round-tripping across the ObjC-Swift bridge. Making Optional conform to _ObjectiveCBridgeable is more or less enough to make this all work, though there are a few additional edge case things that need to be fixed up. We don't want to accept `AnyObject??` as an @objc-compatible type, so special-case Optional in `getForeignRepresentable`. Implements SR-0140 (rdar://problem/27905315).
This commit is contained in:
@@ -2513,6 +2513,18 @@ bool swift::swift_dynamicCast(OpaqueValue *dest,
|
||||
// unwrapping the target. This handles an optional source wrapped within an
|
||||
// existential that Optional conforms to (Any).
|
||||
if (auto srcExistentialType = dyn_cast<ExistentialTypeMetadata>(srcType)) {
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
// If coming from AnyObject, we may want to bridge.
|
||||
if (srcExistentialType->Flags.getSpecialProtocol()
|
||||
== SpecialProtocol::AnyObject) {
|
||||
if (auto targetBridgeWitness = findBridgeWitness(targetType)) {
|
||||
return _dynamicCastClassToValueViaObjCBridgeable(dest, src, srcType,
|
||||
targetType,
|
||||
targetBridgeWitness,
|
||||
flags);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return _dynamicCastFromExistential(dest, src, srcExistentialType,
|
||||
targetType, flags);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user