mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[ObjC Bridging] Consistently bridge block types verbatim
A `@convention(block)` closure in Swift is completely compatible with Objective-C and does not need to be wrapped in a `__SwiftValue` box for use. Previously, it was bridged verbatim when appearing by itself, but could end up boxed when it went through array bridging. The test verifies that: * Objective-C does not see a `__SwiftValue` box * Swift `type(of:)` does not see a `__SwiftValue` box * Objective-C can actually call the closure Resolves rdar://138132321
This commit is contained in:
@@ -1289,9 +1289,8 @@ static id bridgeAnythingNonVerbatimToObjectiveC(OpaqueValue *src,
|
||||
swift_unknownObjectRetain(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Dig through existential types.
|
||||
if (auto srcExistentialTy = dyn_cast<ExistentialTypeMetadata>(srcType)) {
|
||||
else if (auto srcExistentialTy = dyn_cast<ExistentialTypeMetadata>(srcType)) {
|
||||
OpaqueValue *srcInnerValue;
|
||||
const Metadata *srcInnerType;
|
||||
bool isOutOfLine;
|
||||
@@ -1320,10 +1319,9 @@ static id bridgeAnythingNonVerbatimToObjectiveC(OpaqueValue *src,
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Handle metatypes.
|
||||
if (isa<ExistentialMetatypeMetadata>(srcType)
|
||||
|| isa<MetatypeMetadata>(srcType)) {
|
||||
// Handle metatypes and existential metatypes
|
||||
else if (isa<ExistentialMetatypeMetadata>(srcType)
|
||||
|| isa<MetatypeMetadata>(srcType)) {
|
||||
const Metadata *srcMetatypeValue;
|
||||
memcpy(&srcMetatypeValue, src, sizeof(srcMetatypeValue));
|
||||
|
||||
@@ -1342,8 +1340,9 @@ static id bridgeAnythingNonVerbatimToObjectiveC(OpaqueValue *src,
|
||||
return objc_retain(protocolObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Handle bridgeable types.
|
||||
} else if (auto srcBridgeWitness = findBridgeWitness(srcType)) {
|
||||
else if (auto srcBridgeWitness = findBridgeWitness(srcType)) {
|
||||
// Bridge the source value to an object.
|
||||
auto srcBridgedObject =
|
||||
srcBridgeWitness->bridgeToObjectiveC(src, srcType, srcBridgeWitness);
|
||||
@@ -1353,13 +1352,24 @@ static id bridgeAnythingNonVerbatimToObjectiveC(OpaqueValue *src,
|
||||
srcType->vw_destroy(src);
|
||||
|
||||
return (id)srcBridgedObject;
|
||||
}
|
||||
// Handle Errors.
|
||||
} else if (auto srcErrorWitness = findErrorWitness(srcType)) {
|
||||
else if (auto srcErrorWitness = findErrorWitness(srcType)) {
|
||||
// Bridge the source value to an NSError.
|
||||
auto flags = consume ? DynamicCastFlags::TakeOnSuccess
|
||||
: DynamicCastFlags::Default;
|
||||
return dynamicCastValueToNSError(src, srcType, srcErrorWitness, flags);
|
||||
}
|
||||
// Handle functions: "Block" types can be bridged literally
|
||||
else if (auto fn = dyn_cast<FunctionTypeMetadata>(srcType)) {
|
||||
if (fn->getConvention() == FunctionMetadataConvention::Block) {
|
||||
id result;
|
||||
memcpy(&result, src, sizeof(id));
|
||||
if (!consume)
|
||||
swift_unknownObjectRetain(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to boxing.
|
||||
return (id)bridgeAnythingToSwiftValueObject(src, srcType, consume);
|
||||
|
||||
Reference in New Issue
Block a user