mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Runtime: Handle bridging from ObjC objects to Any or boxed types.
This commit is contained in:
@@ -246,6 +246,27 @@ func _bridgeNonVerbatimFromObjectiveC<T>(
|
||||
_ result: inout T?
|
||||
)
|
||||
|
||||
/// Helper stub to upcast to Any and store the result to an inout Any?
|
||||
/// on the C++ runtime's behalf.
|
||||
// COMPILER_INTRINSIC
|
||||
@_silgen_name("_swift_bridgeNonVerbatimFromObjectiveCToAny")
|
||||
public func _bridgeNonVerbatimFromObjectiveCToAny(
|
||||
_ x: AnyObject,
|
||||
_ result: inout Any?
|
||||
) {
|
||||
result = x as Any
|
||||
}
|
||||
|
||||
/// Helper stub to upcast to Optional on the C++ runtime's behalf.
|
||||
// COMPILER_INTRINSIC
|
||||
@_silgen_name("_swift_bridgeNonVerbatimBoxedValue")
|
||||
public func _bridgeNonVerbatimBoxedValue<NativeType>(
|
||||
_ x: UnsafePointer<NativeType>,
|
||||
_ result: inout NativeType?
|
||||
) {
|
||||
result = x.pointee
|
||||
}
|
||||
|
||||
/// Runtime optional to conditionally perform a bridge from an object to a value
|
||||
/// type.
|
||||
///
|
||||
|
||||
@@ -2837,6 +2837,60 @@ extern "C" const Metadata *_swift_getBridgedNonVerbatimObjectiveCType(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// @_silgen_name("_swift_bridgeNonVerbatimFromObjectiveCToAny")
|
||||
// func _bridgeNonVerbatimFromObjectiveCToAny(
|
||||
// x: AnyObject,
|
||||
// inout result: Any?
|
||||
// )
|
||||
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
|
||||
extern "C" void
|
||||
_swift_bridgeNonVerbatimFromObjectiveCToAny(HeapObject *sourceValue,
|
||||
OpaqueValue *destValue);
|
||||
|
||||
// @_silgen_name("_swift_bridgeNonVerbatimBoxedValue")
|
||||
// func _bridgeNonVerbatimBoxedValue<NativeType>(
|
||||
// x: UnsafePointer<NativeType>,
|
||||
// inout result: NativeType?
|
||||
// )
|
||||
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
|
||||
extern "C" void
|
||||
_swift_bridgeNonVerbatimBoxedValue(const OpaqueValue *sourceValue,
|
||||
OpaqueValue *destValue,
|
||||
const Metadata *nativeType);
|
||||
|
||||
// Try bridging by conversion to Any or boxing if applicable.
|
||||
static bool tryBridgeNonVerbatimFromObjectiveCUniversal(
|
||||
HeapObject *sourceValue,
|
||||
const Metadata *nativeType,
|
||||
OpaqueValue *destValue
|
||||
) {
|
||||
// If the type is the Any type, we can bridge by "upcasting" the object
|
||||
// to Any.
|
||||
if (auto nativeExistential = dyn_cast<ExistentialTypeMetadata>(nativeType)) {
|
||||
if (nativeExistential->Protocols.NumProtocols == 0) {
|
||||
_swift_bridgeNonVerbatimFromObjectiveCToAny(sourceValue,
|
||||
destValue);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the value is a box containing a value of the desired type.
|
||||
if (auto srcBox = getAsSwiftValue((id)sourceValue)) {
|
||||
const Metadata *sourceType;
|
||||
const OpaqueValue *sourceBoxedValue;
|
||||
|
||||
std::tie(sourceType, sourceBoxedValue) = getValueFromSwiftValue(srcBox);
|
||||
if (sourceType == nativeType) {
|
||||
_swift_bridgeNonVerbatimBoxedValue(sourceBoxedValue,
|
||||
destValue,
|
||||
nativeType);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// @_silgen_name("_swift_bridgeNonVerbatimFromObjectiveC")
|
||||
// func _bridgeNonVerbatimFromObjectiveC<NativeType>(
|
||||
// x: AnyObject,
|
||||
@@ -2851,12 +2905,12 @@ _swift_bridgeNonVerbatimFromObjectiveC(
|
||||
OpaqueValue *destValue,
|
||||
const Metadata *nativeType_
|
||||
) {
|
||||
if (tryBridgeNonVerbatimFromObjectiveCUniversal(sourceValue, nativeType,
|
||||
destValue))
|
||||
return;
|
||||
|
||||
// Check if the type conforms to _BridgedToObjectiveC.
|
||||
if (const auto *bridgeWitness = findBridgeWitness(nativeType)) {
|
||||
// if the type also conforms to _ConditionallyBridgedToObjectiveC,
|
||||
// make sure it bridges at runtime
|
||||
if (bridgeWitness->isBridgedToObjectiveC(nativeType, nativeType,
|
||||
bridgeWitness)) {
|
||||
// Check if sourceValue has the _ObjectiveCType type required by the
|
||||
// protocol.
|
||||
const Metadata *objectiveCType =
|
||||
@@ -2875,7 +2929,6 @@ _swift_bridgeNonVerbatimFromObjectiveC(
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fail.
|
||||
swift::crash("value type is not bridged to Objective-C");
|
||||
@@ -2895,6 +2948,10 @@ _swift_bridgeNonVerbatimFromObjectiveCConditional(
|
||||
OpaqueValue *destValue,
|
||||
const Metadata *nativeType_
|
||||
) {
|
||||
if (tryBridgeNonVerbatimFromObjectiveCUniversal(sourceValue, nativeType,
|
||||
destValue))
|
||||
return true;
|
||||
|
||||
// Local function that releases the source and returns false.
|
||||
auto fail = [&] () -> bool {
|
||||
swift_unknownRelease(sourceValue);
|
||||
|
||||
Reference in New Issue
Block a user