Skip to content

Commit c5deb93

Browse files
committed
Sema: Force SILGen emission of on-demand synthesized accessors
When an on-demand accessor is synthesized while checking a conformance, make sure it ends up in the 'external declarations' list so that SILGen can emit it. Fixes <rdar://problem/46503121>, and part of <rdar://problem/46186045>.
1 parent 6b31c97 commit c5deb93

File tree

4 files changed

+50
-0
lines changed

4 files changed

+50
-0
lines changed

lib/SILGen/SILGenDecl.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,7 +1396,19 @@ void SILGenModule::emitExternalWitnessTable(ProtocolConformance *c) {
13961396
lastEmittedConformance = root;
13971397
}
13981398

1399+
static bool isDeclaredInPrimaryFile(SILModule &M, Decl *d) {
1400+
auto *dc = d->getDeclContext();
1401+
if (auto *sf = dyn_cast<SourceFile>(dc->getModuleScopeContext()))
1402+
if (M.isWholeModule() || M.getAssociatedContext() == sf)
1403+
return true;
1404+
1405+
return false;
1406+
}
1407+
13991408
void SILGenModule::emitExternalDefinition(Decl *d) {
1409+
if (isDeclaredInPrimaryFile(M, d))
1410+
return;
1411+
14001412
switch (d->getKind()) {
14011413
case DeclKind::Func:
14021414
case DeclKind::Accessor: {

lib/Sema/CodeSynthesis.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,11 @@ void TypeChecker::synthesizeWitnessAccessorsForStorage(
10831083
if (isOnDemandAccessor(storage, kind)) {
10841084
auto synthKind = getSynthKindForAccessorKind(kind);
10851085
triggerSynthesis(*this, storage->getAccessor(kind), synthKind);
1086+
1087+
// Make sure SILGen emits the accessor; on-demand accessors have shared
1088+
// linkage, and if its defined in a different translation unit from the
1089+
// conformance we cannot simply generate an external declaration.
1090+
Context.addExternalDecl(storage->getAccessor(kind));
10861091
}
10871092
});
10881093

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import Foundation
2+
3+
public class Fish {
4+
@NSManaged public var name: String
5+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-swift-frontend -module-name main -emit-silgen -enable-sil-ownership -sdk %S/Inputs -primary-file %s %S/Inputs/nsmanaged-witness-multi-other.swift -I %S/Inputs -I %t -enable-source-import | %FileCheck %s
4+
5+
// RUN: %target-swift-frontend -module-name main -emit-silgen -enable-sil-ownership -sdk %S/Inputs -primary-file %s -primary-file %S/Inputs/nsmanaged-witness-multi-other.swift -I %S/Inputs -I %t -enable-source-import | %FileCheck %s
6+
7+
// RUN: %target-swift-frontend -module-name main -emit-silgen -enable-sil-ownership -sdk %S/Inputs %s %S/Inputs/nsmanaged-witness-multi-other.swift -I %S/Inputs -I %t -enable-source-import | %FileCheck %s
8+
9+
// REQUIRES: objc_interop
10+
import Foundation
11+
12+
public protocol FishProtocol {
13+
var name: String { get set }
14+
}
15+
16+
extension Fish : FishProtocol {}
17+
18+
// Make sure the modify accessor for Fish.name is emitted here even though it
19+
// its storage was declared in a different translation unit
20+
21+
// CHECK-LABEL: sil shared [transparent] [serialized] [thunk] @$s4main4FishCAA0B8ProtocolA2aDP4nameSSvMTW : $@yield_once @convention(witness_method: FishProtocol) (@inout Fish) -> @yields @inout String
22+
// CHECK: function_ref @$s4main4FishC4nameSSvM
23+
// CHECK: return
24+
25+
// CHECK-LABEL: sil shared [serialized] @$s4main4FishC4nameSSvM : $@yield_once @convention(method) (@guaranteed Fish) -> @yields @inout String
26+
// CHECK: objc_method %0 : $Fish, #Fish.name!getter.1.foreign
27+
// CHECK: objc_method %0 : $Fish, #Fish.name!setter.1.foreign
28+
// CHECK: unwind

0 commit comments

Comments
 (0)