Skip to content

Commit 7e1050b

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 36893aa commit 7e1050b

File tree

1 file changed

+18
-11
lines changed

1 file changed

+18
-11
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 18 additions & 11 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,15 @@ static bool isDependentConformance(
961967
if (assocConformance.isInvalid())
962968
return false;
963969

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

@@ -986,12 +996,6 @@ bool IRGenModule::isDependentConformance(
986996
return ::isDependentConformance(*this, conformance, visited);
987997
}
988998

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

0 commit comments

Comments
 (0)