Skip to content

Commit 1ef422d

Browse files
committed
[IRGen] Fix witness table miscompilation.
If a foreign type conforms to a protocol, and that conformance is not resilient, we were emitting an instantantiation function but it would never be called because we weren't emitting the `GenericWitnessTable` that would have contained a reference to it. This was happening because of a missing `isSynthesizedNonUnique()` call in `isDependentConformance()`. rdar://97290618
1 parent 0cc2ee1 commit 1ef422d

File tree

1 file changed

+15
-10
lines changed

1 file changed

+15
-10
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,12 @@ static bool hasDependentTypeWitness(
920920
return false;
921921
}
922922

923+
static bool isSynthesizedNonUnique(const RootProtocolConformance *conformance) {
924+
if (auto normal = dyn_cast<NormalProtocolConformance>(conformance))
925+
return normal->isSynthesizedNonUnique();
926+
return false;
927+
}
928+
923929
static bool isDependentConformance(
924930
IRGenModule &IGM,
925931
const RootProtocolConformance *rootConformance,
@@ -961,11 +967,13 @@ static bool isDependentConformance(
961967
if (assocConformance.isInvalid())
962968
return false;
963969

970+
auto rootConformance = assocConformance.getConcrete()->getRootConformance();
971+
972+
// [*] This condition must be true if getConformanceInfo() would return
973+
// an AccessorConformanceInfo().
964974
if (assocConformance.isAbstract() ||
965-
isDependentConformance(IGM,
966-
assocConformance.getConcrete()
967-
->getRootConformance(),
968-
visited))
975+
isSynthesizedNonUnique(rootConformance) ||
976+
isDependentConformance(IGM, rootConformance, visited))
969977
return true;
970978
}
971979

@@ -986,12 +994,6 @@ bool IRGenModule::isDependentConformance(
986994
return ::isDependentConformance(*this, conformance, visited);
987995
}
988996

989-
static bool isSynthesizedNonUnique(const RootProtocolConformance *conformance) {
990-
if (auto normal = dyn_cast<NormalProtocolConformance>(conformance))
991-
return normal->isSynthesizedNonUnique();
992-
return false;
993-
}
994-
995997
static llvm::Value *
996998
emitConditionalConformancesBuffer(IRGenFunction &IGF,
997999
const ProtocolConformance *substConformance) {
@@ -2142,6 +2144,9 @@ IRGenModule::getConformanceInfo(const ProtocolDecl *protocol,
21422144
// so in theory we could allocate them on a BumpPtrAllocator. But there's not
21432145
// a good one for us to use. (The ASTContext's outlives the IRGenModule in
21442146
// batch mode.)
2147+
//
2148+
// N.B. If you change this condition, you may need to update the condition
2149+
// marked [*] in isDependentConformance().
21452150
if (isDependentConformance(rootConformance) ||
21462151
// Foreign types need to go through the accessor to unique the witness
21472152
// table.

0 commit comments

Comments
 (0)