Skip to content

Commit f73cd75

Browse files
committed
Judge the need for an external key path reference by the overridden base.
We identify overrides using the same key path descriptor as the base, but an overridden base may not have a property descriptor if it's @objc or fragile. Fixes rdar://problem/51479334.
1 parent 0974006 commit f73cd75

File tree

2 files changed

+27
-10
lines changed

2 files changed

+27
-10
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3419,23 +3419,32 @@ SILGenModule::emitKeyPathComponentForDecl(SILLocation loc,
34193419
ArrayRef<ProtocolConformanceRef> indexHashables,
34203420
CanType baseTy,
34213421
bool forPropertyDescriptor) {
3422+
auto baseDecl = storage;
3423+
3424+
// ABI-compatible overrides do not have property descriptors, so we need
3425+
// to reference the overridden declaration instead.
3426+
if (isa<ClassDecl>(baseDecl->getDeclContext())) {
3427+
while (!baseDecl->isValidKeyPathComponent())
3428+
baseDecl = baseDecl->getOverriddenDecl();
3429+
}
3430+
34223431
/// Returns true if a key path component for the given property or
34233432
/// subscript should be externally referenced.
34243433
auto shouldUseExternalKeyPathComponent = [&]() -> bool {
34253434
return (!forPropertyDescriptor &&
3426-
(storage->getModuleContext() != SwiftModule ||
3427-
storage->isResilient(SwiftModule, expansion)) &&
3435+
(baseDecl->getModuleContext() != SwiftModule ||
3436+
baseDecl->isResilient(SwiftModule, expansion)) &&
34283437
// Protocol requirements don't have nor need property descriptors.
3429-
!isa<ProtocolDecl>(storage->getDeclContext()) &&
3438+
!isa<ProtocolDecl>(baseDecl->getDeclContext()) &&
34303439
// Properties that only dispatch via ObjC lookup do not have nor
34313440
// need property descriptors, since the selector identifies the
34323441
// storage.
34333442
// Properties that are not public don't need property descriptors
34343443
// either.
3435-
(!storage->hasAnyAccessors() ||
3436-
(!getAccessorDeclRef(getRepresentativeAccessorForKeyPath(storage))
3444+
(!baseDecl->hasAnyAccessors() ||
3445+
(!getAccessorDeclRef(getRepresentativeAccessorForKeyPath(baseDecl))
34373446
.isForeign &&
3438-
getAccessorDeclRef(getRepresentativeAccessorForKeyPath(storage))
3447+
getAccessorDeclRef(getRepresentativeAccessorForKeyPath(baseDecl))
34393448
.getLinkage(ForDefinition) <= SILLinkage::PublicNonABI)));
34403449
};
34413450

@@ -3465,10 +3474,7 @@ SILGenModule::emitKeyPathComponentForDecl(SILLocation loc,
34653474

34663475
// ABI-compatible overrides do not have property descriptors, so we need
34673476
// to reference the overridden declaration instead.
3468-
auto *baseDecl = externalDecl;
3469-
if (isa<ClassDecl>(baseDecl->getDeclContext())) {
3470-
while (!baseDecl->isValidKeyPathComponent())
3471-
baseDecl = baseDecl->getOverriddenDecl();
3477+
if (baseDecl != externalDecl) {
34723478
externalSubs = SubstitutionMap::getOverrideSubstitutions(baseDecl,
34733479
externalDecl,
34743480
externalSubs);

test/SILGen/keypaths_objc.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,14 @@ func sharedCProperty() {
102102
// CHECK-NOT: external #c_union.some_field
103103
let dataKeyPath: WritableKeyPath<c_union, some_struct>? = \c_union.some_field
104104
}
105+
106+
class OverrideFrameworkObjCProperty: A {
107+
override var counter: Int32 {
108+
get { return 0 }
109+
set { }
110+
}
111+
}
112+
113+
func overrideFrameworkObjCProperty() {
114+
let _ = \OverrideFrameworkObjCProperty.counter
115+
}

0 commit comments

Comments
 (0)