Skip to content

Commit 24abeca

Browse files
authored
Merge pull request #16829 from shajrawi/fix_dynamic_cast
2 parents a5f44c5 + c49a1ff commit 24abeca

File tree

2 files changed

+42
-4
lines changed

2 files changed

+42
-4
lines changed

lib/SIL/DynamicCasts.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,15 @@ swift::classifyDynamicCast(ModuleDecl *M,
323323

324324
// Casting to a less-optional type can always fail.
325325
} else if (sourceObject) {
326-
return atBest(classifyDynamicCast(M, sourceObject, target,
327-
/* isSourceTypeExact */ false,
328-
isWholeModuleOpts),
329-
DynamicCastFeasibility::MaySucceed);
326+
auto result = atBest(classifyDynamicCast(M, sourceObject, target,
327+
/* isSourceTypeExact */ false,
328+
isWholeModuleOpts),
329+
DynamicCastFeasibility::MaySucceed);
330+
if (target.isExistentialType()) {
331+
result = atWorst(result, classifyDynamicCastToProtocol(
332+
M, source, target, isWholeModuleOpts));
333+
}
334+
return result;
330335
}
331336
assert(!sourceObject && !targetObject);
332337

test/SILOptimizer/cast_folding.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,39 @@ public func testCastProtocolTypeProtocolToProtocolTypeType() -> P.Type.Type? {
10321032
return P.Type.self as? P.Type.Type
10331033
}
10341034

1035+
protocol PForOptional {
1036+
}
1037+
1038+
extension Optional: PForOptional {
1039+
}
1040+
1041+
func testCastToPForOptional<T>(_ t: T) -> Bool {
1042+
if let _ = t as? PForOptional {
1043+
return true
1044+
}
1045+
return false
1046+
}
1047+
1048+
// CHECK-LABEL: // testCastToPForOptionalSuccess()
1049+
// CHECK: [[RES:%.*]] = integer_literal $Builtin.Int1, -1
1050+
// CHECK: [[RET:%.*]] = struct $Bool ([[RES]] : $Builtin.Int1)
1051+
// CHECK: return [[RET]] : $Bool
1052+
@inline(never)
1053+
public func testCastToPForOptionalSuccess() -> Bool {
1054+
let t: Int? = 42
1055+
return testCastToPForOptional(t)
1056+
}
1057+
1058+
// CHECK-LABEL: // testCastToPForOptionalFailure()
1059+
// CHECK: [[RES:%.*]] = integer_literal $Builtin.Int1, 0
1060+
// CHECK: [[RET:%.*]] = struct $Bool ([[RES]] : $Builtin.Int1)
1061+
// CHECK: return [[RET]] : $Bool
1062+
@inline(never)
1063+
public func testCastToPForOptionalFailure() -> Bool {
1064+
let t: Int = 42
1065+
return testCastToPForOptional(t)
1066+
}
1067+
10351068
print("test0=\(test0())")
10361069

10371070
print("test1=\(test1())")

0 commit comments

Comments
 (0)