Skip to content

Commit 22f199b

Browse files
authored
Merge pull request #16772 from mikeash/dynamicCast-unwrap-multilevel-optionals
[Runtime] Have swift_dynamicCast unwrap multiple levels of optionals in the source.
2 parents f689af1 + 0dae9b3 commit 22f199b

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

stdlib/public/runtime/Casting.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1866,7 +1866,7 @@ checkDynamicCastFromOptional(OpaqueValue *dest,
18661866
// .Some
18671867
// Single payload enums are guaranteed layout compatible with their
18681868
// payload. Only the source's payload needs to be taken or destroyed.
1869-
return {false, payloadType};
1869+
return checkDynamicCastFromOptional(dest, src, payloadType, targetType, flags);
18701870
}
18711871

18721872
/******************************************************************************/

test/stdlib/Casts.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,26 @@ CastsTests.test("No overrelease of existential boxes in failed casts") {
5050

5151
extension Int : P {}
5252

53+
// Test for SR-7664: Inconsistent optional casting behaviour with generics
54+
// Runtime failed to unwrap multiple levels of Optional when casting.
55+
CastsTests.test("Multi-level optionals can be casted") {
56+
func testSuccess<From, To>(_ x: From, from: From.Type, to: To.Type) {
57+
expectNotNil(x as? To)
58+
}
59+
func testFailure<From, To>(_ x: From, from: From.Type, to: To.Type) {
60+
expectNil(x as? To)
61+
}
62+
testSuccess(42, from: Int?.self, to: Int.self)
63+
testSuccess(42, from: Int??.self, to: Int.self)
64+
testSuccess(42, from: Int???.self, to: Int.self)
65+
testSuccess(42, from: Int???.self, to: Int?.self)
66+
testSuccess(42, from: Int???.self, to: Int??.self)
67+
testSuccess(42, from: Int???.self, to: Int???.self)
68+
testFailure(42, from: Int?.self, to: String.self)
69+
testFailure(42, from: Int??.self, to: String.self)
70+
testFailure(42, from: Int???.self, to: String.self)
71+
}
72+
5373
#if _runtime(_ObjC)
5474
extension CFBitVector : P {
5575
static func makeImmutable(from values: Array<UInt8>) -> CFBitVector {

0 commit comments

Comments
 (0)