Skip to content

Commit 24af84d

Browse files
authored
Merge pull request #76753 from kubamracek/embedded-existential-deserialize
[embedded] Force deserialization of wtables when needed to support class-bound existentials
2 parents bd9095e + 151e587 commit 24af84d

File tree

3 files changed

+48
-9
lines changed

3 files changed

+48
-9
lines changed

lib/SIL/IR/Linker.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ bool SILLinkerVisitor::processFunction(SILFunction *F) {
161161
}
162162

163163
bool SILLinkerVisitor::processConformance(ProtocolConformanceRef conformanceRef) {
164-
visitProtocolConformance(conformanceRef);
164+
visitProtocolConformance(conformanceRef, false);
165165
process();
166166
return Changed;
167167
}
@@ -247,12 +247,15 @@ static bool mustDeserializeProtocolConformance(SILModule &M,
247247
&& conformance->isSynthesized();
248248
}
249249

250-
void SILLinkerVisitor::visitProtocolConformance(ProtocolConformanceRef ref) {
250+
void SILLinkerVisitor::visitProtocolConformance(
251+
ProtocolConformanceRef ref, bool referencedFromInitExistential) {
251252
// If an abstract protocol conformance was passed in, do nothing.
252253
if (ref.isAbstract())
253254
return;
254255

255-
bool mustDeserialize = mustDeserializeProtocolConformance(Mod, ref);
256+
bool isEmbedded = Mod.getOptions().EmbeddedSwift;
257+
bool mustDeserialize = (isEmbedded && referencedFromInitExistential) ||
258+
mustDeserializeProtocolConformance(Mod, ref);
256259

257260
// Otherwise try and lookup a witness table for C.
258261
ProtocolConformance *C = ref.getConcrete();
@@ -305,7 +308,7 @@ void SILLinkerVisitor::visitProtocolConformance(ProtocolConformanceRef ref) {
305308
// However, we *must* pull in shared clang-importer-derived conformances
306309
// we potentially use, since we may not otherwise have a local definition.
307310
if (mustDeserializeProtocolConformance(Mod, c))
308-
visitProtocolConformance(c);
311+
visitProtocolConformance(c, referencedFromInitExistential);
309312
};
310313

311314
// For each entry in the witness table...
@@ -355,7 +358,7 @@ void SILLinkerVisitor::visitApplySubstitutions(SubstitutionMap subs) {
355358
// However, we *must* pull in shared clang-importer-derived conformances
356359
// we potentially use, since we may not otherwise have a local definition.
357360
if (mustDeserializeProtocolConformance(Mod, conformance)) {
358-
visitProtocolConformance(conformance);
361+
visitProtocolConformance(conformance, false);
359362
}
360363
}
361364
}
@@ -371,7 +374,7 @@ void SILLinkerVisitor::visitInitExistentialAddrInst(
371374
// visiting the open_existential_addr/witness_method before the
372375
// init_existential_inst.
373376
for (ProtocolConformanceRef C : IEI->getConformances()) {
374-
visitProtocolConformance(C);
377+
visitProtocolConformance(C, true);
375378
}
376379
}
377380

@@ -385,9 +388,10 @@ void SILLinkerVisitor::visitInitExistentialRefInst(
385388
// not going to be smart about this to enable avoiding any issues with
386389
// visiting the protocol_method before the init_existential_inst.
387390
for (ProtocolConformanceRef C : IERI->getConformances()) {
388-
visitProtocolConformance(C);
391+
visitProtocolConformance(C, true);
389392
}
390393
}
394+
391395
void SILLinkerVisitor::visitAllocRefDynamicInst(AllocRefDynamicInst *ARI) {
392396
if (!isLinkAll())
393397
return;

lib/SIL/IR/Linker.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,11 @@ class SILLinkerVisitor : public SILInstructionVisitor<SILLinkerVisitor, void> {
119119
void visitFunctionRefInst(FunctionRefInst *FRI);
120120
void visitDynamicFunctionRefInst(DynamicFunctionRefInst *FRI);
121121
void visitPreviousDynamicFunctionRefInst(PreviousDynamicFunctionRefInst *FRI);
122-
void visitProtocolConformance(ProtocolConformanceRef C);
122+
void visitProtocolConformance(ProtocolConformanceRef C,
123+
bool referencedFromInitExistential);
123124
void visitApplySubstitutions(SubstitutionMap subs);
124125
void visitWitnessMethodInst(WitnessMethodInst *WMI) {
125-
visitProtocolConformance(WMI->getConformance());
126+
visitProtocolConformance(WMI->getConformance(), false);
126127
}
127128
void visitInitExistentialAddrInst(InitExistentialAddrInst *IEI);
128129
void visitInitExistentialRefInst(InitExistentialRefInst *IERI);
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %{python} %utils/split_file.py -o %t %s
3+
4+
// RUN: %target-swift-frontend -emit-module -o %t/MyModule.swiftmodule %t/MyModule.swift -enable-experimental-feature Embedded -parse-as-library
5+
// RUN: %target-swift-frontend -c -I %t %t/Main.swift -enable-experimental-feature Embedded -o %t/a.o
6+
7+
// REQUIRES: swift_in_compiler
8+
// REQUIRES: OS=macosx || OS=linux-gnu
9+
10+
// BEGIN MyModule.swift
11+
12+
public protocol ClassBound: AnyObject {
13+
func foo()
14+
}
15+
16+
class MyGenericClass<T> {
17+
var typ: String
18+
init(typ: String) { self.typ = typ }
19+
}
20+
extension MyGenericClass: ClassBound {
21+
func foo() { print("MyGenericClass<\(typ)>.foo()") }
22+
}
23+
24+
public func factory() -> any ClassBound {
25+
return MyGenericClass<String>(typ: "String")
26+
}
27+
28+
// BEGIN Main.swift
29+
30+
import MyModule
31+
32+
var arr: [any ClassBound] = [factory()]
33+
arr[0].foo()
34+
// CHECK: MyGenericClass<String>.foo()

0 commit comments

Comments
 (0)