Skip to content

Commit bc1443e

Browse files
authored
Merge pull request #60014 from slavapestov/fix-rdar93822961
IRGen: Exclude classes defined in generic contexts from fast cast optimization
2 parents b928078 + c80d8e6 commit bc1443e

File tree

2 files changed

+22
-2
lines changed

2 files changed

+22
-2
lines changed

lib/IRGen/GenCast.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,14 +1070,19 @@ llvm::Value *irgen::emitFastClassCastIfPossible(IRGenFunction &IGF,
10701070
if (!classTy)
10711071
return nullptr;
10721072

1073+
ClassDecl *toClass = classTy->getDecl();
1074+
1075+
// Also exclude non-generic classes nested inside other generic types.
1076+
if (toClass->isGenericContext())
1077+
return nullptr;
1078+
10731079
// TODO: we could use the ClassHierarchyAnalysis do also handle "effectively"
10741080
// final classes, e.g. not-subclassed internal classes in WMO.
10751081
// This would need some rearchitecting of ClassHierarchyAnalysis to make it
10761082
// available in IRGen.
1077-
ClassDecl *toClass = classTy->getDecl();
10781083
if (!toClass->isFinal())
10791084
return nullptr;
1080-
1085+
10811086
AncestryOptions forbidden = AncestryOptions(AncestryFlags::ObjC) |
10821087
AncestryFlags::Resilient |
10831088
AncestryFlags::ResilientOther |

test/Casting/fast_class_casts.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ final class DerivedFromResilient : ResilientClasses.OpenBase {
2828
}
2929

3030
final class Generic<T> : Classes.OpenBase {
31+
final class Inner : Classes.OpenBase {}
3132
}
3233

3334
// CHECK-LABEL: define {{.*}} @"$s4Main14castToNonfinaly7Classes0D0CSgAC4BaseCF"
@@ -102,6 +103,15 @@ func castToGeneric(_ b: Classes.OpenBase) -> Generic<Int>? {
102103
return b as? Generic<Int>
103104
}
104105

106+
// CHECK-LABEL: define {{.*}} @"$s4Main18castToGenericInneryAA0D0C0E0CySi_GSg7Classes8OpenBaseCF"
107+
// CHECK: @swift_dynamicCastClass
108+
// CHECK: }
109+
@inline(never)
110+
func castToGenericInner(_ b: Classes.OpenBase) -> Generic<Int>.Inner? {
111+
return b as? Generic<Int>.Inner
112+
}
113+
114+
105115
// CHECK-LABEL: define {{.*}} @"$s4Main14getAnyHashableys0cD0VAA8InternalCF"
106116
@inline(never)
107117
func getAnyHashable(_ i: Internal) -> AnyHashable {
@@ -153,6 +163,11 @@ func test() {
153163
print(castToGeneric(Classes.OpenBase()) as Any)
154164
// CHECK-OUTPUT: Optional(Main.Generic<Swift.Int>)
155165
print(castToGeneric(Generic<Int>()) as Any)
166+
167+
// CHECK-OUTPUT: nil
168+
print(castToGenericInner(Classes.OpenBase()) as Any)
169+
// CHECK-OUTPUT: Optional(Main.Generic<Swift.Int>.Inner)
170+
print(castToGenericInner(Generic<Int>.Inner()) as Any)
156171
}
157172

158173
test()

0 commit comments

Comments
 (0)