Skip to content

Commit 77df286

Browse files
authored
Merge pull request #3829 from jckarter/cast-structural-type-from-boxed-anyobject
Runtime: Let structural types be cast out of boxed AnyObjects too.
2 parents 85806a8 + d206bb5 commit 77df286

File tree

2 files changed

+38
-15
lines changed

2 files changed

+38
-15
lines changed

stdlib/public/runtime/Casting.cpp

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2281,6 +2281,14 @@ bool swift::swift_dynamicCast(OpaqueValue *dest,
22812281
if (!srcType)
22822282
return unwrapResult.success;
22832283

2284+
#if SWIFT_OBJC_INTEROP
2285+
// A class or AnyObject reference may point at a boxed SwiftValue.
2286+
if (tryDynamicCastBoxedSwiftValue(dest, src, srcType,
2287+
targetType, flags)) {
2288+
return true;
2289+
}
2290+
#endif
2291+
22842292
switch (targetType->getKind()) {
22852293
// Handle wrapping an Optional target.
22862294
case MetadataKind::Optional: {
@@ -2411,17 +2419,6 @@ bool swift::swift_dynamicCast(OpaqueValue *dest,
24112419
if (tryDynamicCastNSErrorToValue(dest, src, srcType, targetType, flags)) {
24122420
return true;
24132421
}
2414-
#endif
2415-
SWIFT_FALLTHROUGH;
2416-
}
2417-
2418-
case MetadataKind::Existential: {
2419-
#if SWIFT_OBJC_INTEROP
2420-
// A class or AnyObject reference may point at a boxed SwiftValue.
2421-
if (tryDynamicCastBoxedSwiftValue(dest, src, srcType,
2422-
targetType, flags)) {
2423-
return true;
2424-
}
24252422
#endif
24262423
break;
24272424
}
@@ -2436,6 +2433,7 @@ bool swift::swift_dynamicCast(OpaqueValue *dest,
24362433
}
24372434
break;
24382435

2436+
case MetadataKind::Existential:
24392437
case MetadataKind::ExistentialMetatype:
24402438
case MetadataKind::Enum:
24412439
case MetadataKind::Optional:

test/1_stdlib/BridgeIdAsAny.swift.gyb

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,18 +94,41 @@ func boxedTypeRoundTripsThroughDynamicCasting(original: KnownUnbridged,
9494
expectEqual(bridged as? String, nil)
9595
}
9696

97+
func tupleCanBeDynamicallyCast(original: (Int, String),
98+
bridged: AnyObject) {
99+
expectTrue(original == bridged as! (Int, String))
100+
}
101+
func metatypeCanBeDynamicallyCast(original: Int.Type,
102+
bridged: AnyObject) {
103+
expectTrue(original == bridged as! Int.Type)
104+
expectTrue(original == bridged as! Any.Type)
105+
}
106+
107+
func guineaPigFunction() -> Int {
108+
return 1738
109+
}
110+
111+
func functionCanBeDynamicallyCast(original: () -> Int,
112+
bridged: AnyObject) {
113+
expectEqual(original(), (bridged as! () -> Int)())
114+
expectEqual(original(), try! (bridged as! () throws -> Int)())
115+
}
116+
97117
// We want to exhaustively check all paths through the bridging and dynamic
98118
// casting infrastructure, so expand out test cases that wrap the different
99119
// interesting bridging cases in different kinds of existential container.
100120
%{
101121
testCases = [
102-
("classes", "LifetimeTracked(0)", "bridgedObjectPreservesIdentity"),
103-
("strings", '"vitameatavegamin"', "stringBridgesToEqualNSString"),
104-
("unbridged type", "KnownUnbridged()", "boxedTypeRoundTripsThroughDynamicCasting"),
122+
("classes", "LifetimeTracked(0)", "bridgedObjectPreservesIdentity", True),
123+
("strings", '"vitameatavegamin"', "stringBridgesToEqualNSString", True),
124+
("unbridged type", "KnownUnbridged()", "boxedTypeRoundTripsThroughDynamicCasting", True),
125+
("tuple", '(1, "2")', "tupleCanBeDynamicallyCast", False),
126+
("metatype", 'Int.self', "metatypeCanBeDynamicallyCast", False),
127+
("function", 'guineaPigFunction', "functionCanBeDynamicallyCast", False),
105128
]
106129
}%
107130

108-
% for testName, valueExpr, testFunc in testCases:
131+
% for testName, valueExpr, testFunc, conformsToError in testCases:
109132
BridgeAnything.test("${testName}") {
110133
do {
111134
let x = ${valueExpr}
@@ -120,13 +143,15 @@ BridgeAnything.test("${testName}") {
120143
${testFunc}(original: x, bridged: _bridgeAnythingToObjectiveC(xInAnyInAny))
121144
${testFunc}(original: x, bridged: _bridgeAnythingNonVerbatimToObjectiveC(xInAnyInAny))
122145

146+
% if conformsToError:
123147
let xInError: Error = x
124148
${testFunc}(original: x, bridged: _bridgeAnythingToObjectiveC(xInError))
125149
${testFunc}(original: x, bridged: _bridgeAnythingNonVerbatimToObjectiveC(xInError))
126150

127151
let xInErrorInAny = wantonlyWrapInAny(xInError)
128152
${testFunc}(original: x, bridged: _bridgeAnythingToObjectiveC(xInErrorInAny))
129153
${testFunc}(original: x, bridged: _bridgeAnythingNonVerbatimToObjectiveC(xInErrorInAny))
154+
% end
130155
}
131156
}
132157
% end

0 commit comments

Comments
 (0)