mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Introduce _ConditionallyBridgedToObjectiveC.bridgeFromObjectiveCConditional.
This entry point is used in conditional downcasts (as?) to attempt to bridge from an Objective-C class down to a specific native type (e.g., array, dictionary), bridging all elements eagerly so that it can produce nil if the bridging would fail. This is the scaffolding for <rdar://problem/17319154>, and makes the example there work, but there is much more cleanup and optimization to do. Swift SVN r18999
This commit is contained in:
@@ -1448,7 +1448,7 @@ struct _BridgedToObjectiveCWitnessTable {
|
||||
|
||||
// func bridgeToObjectiveC() -> ObjectiveCType
|
||||
HeapObject *(*bridgeToObjectiveC)(OpaqueValue *self, const Metadata *Self);
|
||||
// func bridgeFromObjectiveC(x: ObjectiveCType) -> Self?
|
||||
// class func bridgeFromObjectiveC(x: ObjectiveCType) -> Self?
|
||||
OpaqueExistentialContainer (*bridgeFromObjectiveC)(HeapObject *sourceValue,
|
||||
const Metadata *self,
|
||||
const Metadata *selfType);
|
||||
@@ -1466,6 +1466,12 @@ struct _ConditionallyBridgedToObjectiveCWitnessTable {
|
||||
|
||||
// class func isBridgedToObjectiveC() -> bool
|
||||
bool (*isBridgedToObjectiveC)(const Metadata *value, const Metadata *T);
|
||||
|
||||
// class func bridgeFromObjectiveCConditional(x: ObjectiveCType) -> Self?
|
||||
OpaqueExistentialContainer (*bridgeFromObjectiveCConditional)(
|
||||
HeapObject *sourceValue,
|
||||
const Metadata *self,
|
||||
const Metadata *selfType);
|
||||
};
|
||||
// }
|
||||
|
||||
@@ -1583,6 +1589,56 @@ swift_bridgeNonVerbatimFromObjectiveC(
|
||||
return _TFSs26_injectNothingIntoOptionalU__FT_GSqQ__(nativeType);
|
||||
}
|
||||
|
||||
// @asmname("swift_bridgeNonVerbatimFromObjectiveCConditional")
|
||||
// func _bridgeNonVerbatimFromObjectiveCConditional<NativeType>(
|
||||
// x: AnyObject, nativeType: NativeType.Type
|
||||
// ) -> NativeType?
|
||||
extern "C" OpaqueExistentialContainer
|
||||
swift_bridgeNonVerbatimFromObjectiveCConditional(
|
||||
HeapObject *sourceValue,
|
||||
const Metadata *nativeType,
|
||||
const Metadata *nativeType_
|
||||
) {
|
||||
// Local function that releases the source and produces a nil.
|
||||
auto produceNil = [&] () -> OpaqueExistentialContainer {
|
||||
swift_unknownRelease(sourceValue);
|
||||
return _TFSs26_injectNothingIntoOptionalU__FT_GSqQ__(nativeType);
|
||||
};
|
||||
|
||||
// Check if the type conforms to _BridgedToObjectiveC.
|
||||
const auto *bridgeWitness = findBridgeWitness(nativeType);
|
||||
if (!bridgeWitness)
|
||||
return produceNil();
|
||||
|
||||
// Dig out the Objective-C class type through which the native type
|
||||
// is bridged.
|
||||
const Metadata *objectiveCType =
|
||||
bridgeWitness->getObjectiveCType(nativeType, nativeType);
|
||||
|
||||
// Check whether we can downcast the source value to the Objective-C
|
||||
// type.
|
||||
auto sourceValueAsObjectiveCType =
|
||||
const_cast<void*>(swift_dynamicCastUnknownClass(sourceValue,
|
||||
objectiveCType));
|
||||
if (!sourceValueAsObjectiveCType)
|
||||
return produceNil();
|
||||
|
||||
// If the type also conforms to _ConditionallyBridgedToObjectiveC,
|
||||
// use conditional bridging.
|
||||
if (auto conditionalWitness = findConditionalBridgeWitness(nativeType)) {
|
||||
return conditionalWitness->bridgeFromObjectiveCConditional(
|
||||
static_cast<HeapObject*>(sourceValueAsObjectiveCType),
|
||||
nativeType, nativeType);
|
||||
}
|
||||
|
||||
// Perform direct bridging. bridgeFromObjectiveC returns `Self?`;
|
||||
// this function returns `NativeType`, so we don't need to re-wrap
|
||||
// the optional.
|
||||
return bridgeWitness->bridgeFromObjectiveC(
|
||||
static_cast<HeapObject*>(sourceValueAsObjectiveCType),
|
||||
nativeType, nativeType);
|
||||
}
|
||||
|
||||
// func isBridgedNonVerbatimToObjectiveC<T>(x: T.Type) -> Bool
|
||||
extern "C" bool swift_isBridgedNonVerbatimToObjectiveC(
|
||||
const Metadata *value, const Metadata *T
|
||||
|
||||
Reference in New Issue
Block a user