Skip to content

Commit 94a9a9a

Browse files
committed
IRGen: Don't assert on keypaths that use a subclass as root
class A { var x : Int = 0 } class B : A {} _ = \B.x rdar://46562046
1 parent 192954c commit 94a9a9a

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

lib/IRGen/GenKeyPath.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,21 @@ emitKeyPathComponent(IRGenModule &IGM,
837837
// ObjC-ness and resilience of the class hierarchy, there might be a few
838838
// different ways we need to go about this.
839839
if (loweredBaseTy.getClassOrBoundGenericClass()) {
840+
841+
// Walk up the class hierarchy to find the class decl that matches the
842+
// property's class decl and use this type to determin the field access.
843+
auto propertyBaseDecl = property->getDeclContext()->getSelfClassDecl();
844+
auto currentBaseTy = loweredBaseTy.getASTType();
845+
while (currentBaseTy->getClassOrBoundGenericClass() != propertyBaseDecl &&
846+
currentBaseTy->getClassOrBoundGenericClass()->hasSuperclass()) {
847+
currentBaseTy = currentBaseTy->getClassOrBoundGenericClass()
848+
->getSuperclass()
849+
->getCanonicalType();
850+
}
851+
assert(currentBaseTy->getClassOrBoundGenericClass() == propertyBaseDecl);
852+
loweredBaseTy = IGM.getLoweredType(AbstractionPattern::getOpaque(),
853+
currentBaseTy->getWithoutSpecifierType());
854+
840855
switch (getClassFieldAccess(IGM, loweredBaseTy, property)) {
841856
case FieldAccess::ConstantDirect: {
842857
// Known constant fixed offset.

test/IRGen/keypaths.sil

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,17 @@ sil_vtable C2 {}
8787
// CHECK-32-SAME: <i32 0x0380_0008> }>
8888
// CHECK-64-SAME: <i32 0x0380_0010> }>
8989

90+
// -- %d1: C1.x
91+
// CHECK: [[KP_D1:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
92+
// CHECK-SAME: [[WORD]]* @keypath_once
93+
// CHECK-SAME: @"symbolic
94+
// CHECK-SAME: @"symbolic
95+
// -- instantiable in-line, size 4
96+
// CHECK-SAME: <i32 0x8000_0004>,
97+
// -- 0x0300_0000 (class) + mutable + offset of C.x
98+
// CHECK-32-SAME: <i32 0x0380_0008> }>
99+
// CHECK-64-SAME: <i32 0x0380_0010> }>
100+
90101
// -- %e: C.y
91102
// CHECK: [[KP_E:@keypath(\..*)?]] = private global <{ {{.*}} }> <{
92103
// CHECK-SAME: [[WORD]]* @keypath_once
@@ -218,9 +229,10 @@ entry:
218229
%b = keypath $KeyPath<S, String>, (root $S; stored_property #S.y : $String)
219230
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_C]] to i8*), i8* undef)
220231
%c = keypath $KeyPath<S, C>, (root $S; stored_property #S.z : $C)
221-
222232
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_D]] to i8*), i8* undef)
223233
%d = keypath $KeyPath<C, Int>, (root $C; stored_property #C.x : $Int)
234+
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_D1]] to i8*), i8* undef)
235+
%d1 = keypath $KeyPath<C1, Int>, (root $C1; stored_property #C.x : $Int)
224236
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_E]] to i8*), i8* undef)
225237
%e = keypath $KeyPath<C, String>, (root $C; stored_property #C.y : $String)
226238
// CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_F]] to i8*), i8* undef)

0 commit comments

Comments
 (0)