|
31 | 31 | #include "Private.h"
|
32 | 32 | #include "../SwiftShims/RuntimeShims.h"
|
33 | 33 | #include "stddef.h"
|
| 34 | +#if SWIFT_OBJC_INTEROP |
| 35 | +#include "swift/Runtime/ObjCBridge.h" |
| 36 | +#include "SwiftValue.h" |
| 37 | +#endif |
34 | 38 |
|
35 | 39 | #include <cstring>
|
36 | 40 | #include <type_traits>
|
@@ -2086,6 +2090,65 @@ checkDynamicCastFromOptional(OpaqueValue *dest,
|
2086 | 2090 | return {false, payloadType};
|
2087 | 2091 | }
|
2088 | 2092 |
|
| 2093 | +#if SWIFT_OBJC_INTEROP |
| 2094 | +/// Try to unbox a SwiftValue box to perform a dynamic cast. |
| 2095 | +static bool tryDynamicCastBoxedSwiftValue(OpaqueValue *dest, |
| 2096 | + OpaqueValue *src, |
| 2097 | + const Metadata *srcType, |
| 2098 | + const Metadata *targetType, |
| 2099 | + DynamicCastFlags flags) { |
| 2100 | + // Swift type should be AnyObject or a class type. |
| 2101 | + if (!srcType->isAnyClass()) { |
| 2102 | + auto existential = dyn_cast<ExistentialTypeMetadata>(srcType); |
| 2103 | + if (!existential || |
| 2104 | + existential->Flags.getSpecialProtocol() |
| 2105 | + != SpecialProtocol::AnyObject) |
| 2106 | + return false; |
| 2107 | + } |
| 2108 | + |
| 2109 | + id srcObject; |
| 2110 | + memcpy(&srcObject, src, sizeof(id)); |
| 2111 | + |
| 2112 | + // Do we have a SwiftValue? |
| 2113 | + SwiftValue *srcSwiftValue = getAsSwiftValue(srcObject); |
| 2114 | + if (!srcSwiftValue) |
| 2115 | + return false; |
| 2116 | + |
| 2117 | + // If so, extract the boxed value and try to cast it. |
| 2118 | + const Metadata *boxedType; |
| 2119 | + const OpaqueValue *boxedValue; |
| 2120 | + std::tie(boxedType, boxedValue) |
| 2121 | + = getValueFromSwiftValue(srcSwiftValue); |
| 2122 | + |
| 2123 | + // We can't touch the value from the box because it may be |
| 2124 | + // multiply-referenced. |
| 2125 | + // TODO: Check for uniqueness and consume if box is unique? |
| 2126 | + |
| 2127 | + // Does the boxed type exactly match the target type we're looking for? |
| 2128 | + if (boxedType == targetType) { |
| 2129 | + targetType->vw_initializeWithCopy(dest, |
| 2130 | + const_cast<OpaqueValue*>(boxedValue)); |
| 2131 | + // Release the box if we need to. |
| 2132 | + if (flags & DynamicCastFlags::TakeOnSuccess) |
| 2133 | + objc_release((id)srcSwiftValue); |
| 2134 | + return true; |
| 2135 | + } |
| 2136 | + |
| 2137 | + // Maybe we can cast the boxed value to our destination type somehow. |
| 2138 | + auto innerFlags = flags - DynamicCastFlags::TakeOnSuccess |
| 2139 | + - DynamicCastFlags::DestroyOnFailure; |
| 2140 | + if (swift_dynamicCast(dest, const_cast<OpaqueValue*>(boxedValue), |
| 2141 | + boxedType, targetType, innerFlags)) { |
| 2142 | + // Release the box if we need to. |
| 2143 | + if (flags & DynamicCastFlags::TakeOnSuccess) |
| 2144 | + objc_release((id)srcSwiftValue); |
| 2145 | + return true; |
| 2146 | + } |
| 2147 | + |
| 2148 | + return false; |
| 2149 | +} |
| 2150 | +#endif |
| 2151 | + |
2089 | 2152 | /// Perform a dynamic cast to an arbitrary type.
|
2090 | 2153 | SWIFT_RT_ENTRY_VISIBILITY
|
2091 | 2154 | bool swift::swift_dynamicCast(OpaqueValue *dest,
|
@@ -2230,14 +2293,24 @@ bool swift::swift_dynamicCast(OpaqueValue *dest,
|
2230 | 2293 | if (tryDynamicCastNSErrorToValue(dest, src, srcType, targetType, flags)) {
|
2231 | 2294 | return true;
|
2232 | 2295 | }
|
| 2296 | +#endif |
| 2297 | + SWIFT_FALLTHROUGH; |
| 2298 | + } |
| 2299 | + |
| 2300 | + case MetadataKind::Existential: { |
| 2301 | +#if SWIFT_OBJC_INTEROP |
| 2302 | + // A class or AnyObject reference may point at a boxed SwiftValue. |
| 2303 | + if (tryDynamicCastBoxedSwiftValue(dest, src, srcType, |
| 2304 | + targetType, flags)) { |
| 2305 | + return true; |
| 2306 | + } |
2233 | 2307 | #endif
|
2234 | 2308 | break;
|
2235 | 2309 | }
|
2236 | 2310 |
|
| 2311 | + case MetadataKind::ExistentialMetatype: |
2237 | 2312 | case MetadataKind::Enum:
|
2238 | 2313 | case MetadataKind::Optional:
|
2239 |
| - case MetadataKind::Existential: |
2240 |
| - case MetadataKind::ExistentialMetatype: |
2241 | 2314 | case MetadataKind::Function:
|
2242 | 2315 | case MetadataKind::HeapLocalVariable:
|
2243 | 2316 | case MetadataKind::HeapGenericLocalVariable:
|
@@ -2549,7 +2622,7 @@ static id bridgeAnythingNonVerbatimToObjectiveC(OpaqueValue *src,
|
2549 | 2622 | if (consume) {
|
2550 | 2623 | if (canTake) {
|
2551 | 2624 | if (isOutOfLine) {
|
2552 |
| - // Should only be true of opaque existentials. |
| 2625 | + // Should only be true of opaque existentials right now. |
2553 | 2626 | assert(srcExistentialTy->getRepresentation()
|
2554 | 2627 | == ExistentialTypeRepresentation::Opaque);
|
2555 | 2628 | auto container = reinterpret_cast<OpaqueExistentialContainer*>(src);
|
@@ -2581,8 +2654,8 @@ static id bridgeAnythingNonVerbatimToObjectiveC(OpaqueValue *src,
|
2581 | 2654 | return (id)srcBridgedObject;
|
2582 | 2655 | }
|
2583 | 2656 |
|
2584 |
| - // TODO: Fall back to boxing here. |
2585 |
| - crash("unimplemented boxing bridge"); |
| 2657 | + // Fall back to boxing. |
| 2658 | + return (id)bridgeAnythingToSwiftValueObject(src, srcType, consume); |
2586 | 2659 | }
|
2587 | 2660 |
|
2588 | 2661 | SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
|
|
0 commit comments