@@ -240,14 +240,28 @@ void SILModule::flushDeletedInsts() {
240240
241241SILWitnessTable *
242242SILModule::lookUpWitnessTable (const ProtocolConformance *C) {
243- assert (C && " null conformance passed to lookUpWitnessTable" );
243+ // First try to lookup a specialized witness table for that conformance.
244+ if (auto *wt = lookUpWitnessTable (C, /* isSpecialized=*/ true )) {
245+ return wt;
246+ }
247+ return lookUpWitnessTable (C, /* isSpecialized=*/ false );
248+ }
244249
245- // Attempt to lookup the witness table from the table.
246- auto found = WitnessTableMap.find (C);
247- if (found == WitnessTableMap.end ())
248- return nullptr ;
250+ SILWitnessTable *
251+ SILModule::lookUpWitnessTable (const ProtocolConformance *C, bool isSpecialized) {
252+ assert (C && " null conformance passed to lookUpWitnessTable" );
249253
250- return found->second ;
254+ if (isSpecialized) {
255+ // First try to lookup a specialized witness table for that conformance.
256+ auto foundSpec = specializedWitnessTableMap.find (C);
257+ if (foundSpec != specializedWitnessTableMap.end ())
258+ return foundSpec->second ;
259+ } else if (auto *rootConf = dyn_cast<RootProtocolConformance>(C)) {
260+ auto found = WitnessTableMap.find (rootConf);
261+ if (found != WitnessTableMap.end ())
262+ return found->second ;
263+ }
264+ return nullptr ;
251265}
252266
253267SILDefaultWitnessTable *
@@ -287,7 +301,9 @@ void SILModule::deleteWitnessTable(SILWitnessTable *Wt) {
287301 auto Conf = Wt->getConformance ();
288302 assert (lookUpWitnessTable (Conf) == Wt);
289303 getSILLoader ()->invalidateWitnessTable (Wt);
290- WitnessTableMap.erase (Conf);
304+ specializedWitnessTableMap.erase (Conf);
305+ if (auto *rootConf = dyn_cast<RootProtocolConformance>(Conf))
306+ WitnessTableMap.erase (rootConf);
291307 witnessTables.erase (Wt);
292308}
293309
@@ -579,15 +595,24 @@ SILModule::lookUpFunctionInWitnessTable(ProtocolConformanceRef C,
579595 linker.processConformance (C);
580596 }
581597 ProtocolConformance *conf = C.getConcrete ();
582- if (auto *inheritedC = dyn_cast<InheritedProtocolConformance>(conf))
583- conf = inheritedC->getInheritedConformance ();
584-
585- if (!isa<SpecializedProtocolConformance>(conf) || !lookupInSpecializedWitnessTable) {
586- conf = conf->getRootConformance ();
598+ SILWitnessTable *wt = nullptr ;
599+
600+ if (lookupInSpecializedWitnessTable) {
601+ wt = lookUpWitnessTable (conf);
602+ if (!wt) {
603+ if (auto *inheritedC = dyn_cast<InheritedProtocolConformance>(conf)) {
604+ conf = inheritedC->getInheritedConformance ();
605+ wt = lookUpWitnessTable (conf);
606+ }
607+ if (!wt && !isa<SpecializedProtocolConformance>(conf)) {
608+ conf = conf->getRootConformance ();
609+ wt = lookUpWitnessTable (conf);
610+ }
611+ }
612+ } else {
613+ wt = lookUpWitnessTable (conf->getRootConformance ());
587614 }
588615
589- SILWitnessTable *wt = lookUpWitnessTable (conf);
590-
591616 if (!wt) {
592617 LLVM_DEBUG (llvm::dbgs () << " Failed speculative lookup of "
593618 " witness for: " ;
0 commit comments