@@ -439,6 +439,28 @@ static bool isAsyncSequenceFailure(AssociatedTypeDecl *assocType) {
439439 return assocType->getName () == assocType->getASTContext ().Id_Failure ;
440440}
441441
442+ static Type resolveTypeWitnessViaParameterizedProtocol (
443+ Type t, AssociatedTypeDecl *assocType) {
444+ if (auto *pct = t->getAs <ProtocolCompositionType>()) {
445+ for (auto member : pct->getMembers ()) {
446+ if (auto result = resolveTypeWitnessViaParameterizedProtocol (
447+ member, assocType)) {
448+ return result;
449+ }
450+ }
451+ } else if (auto *ppt = t->getAs <ParameterizedProtocolType>()) {
452+ auto *proto = ppt->getProtocol ();
453+ unsigned i = 0 ;
454+ for (auto *otherAssocType : proto->getPrimaryAssociatedTypes ()) {
455+ if (otherAssocType->getName () == assocType->getName ())
456+ return ppt->getArgs ()[i];
457+ ++i;
458+ }
459+ }
460+
461+ return Type ();
462+ }
463+
442464// / Attempt to resolve a type witness via member name lookup.
443465static ResolveWitnessResult resolveTypeWitnessViaLookup (
444466 NormalProtocolConformance *conformance,
@@ -456,6 +478,23 @@ static ResolveWitnessResult resolveTypeWitnessViaLookup(
456478 });
457479 }
458480
481+ // Look for a parameterized protocol type in the conformance context's
482+ // inheritance clause.
483+ bool deducedFromParameterizedProtocolType = false ;
484+ auto inherited = (isa<NominalTypeDecl>(dc)
485+ ? cast<NominalTypeDecl>(dc)->getInherited ()
486+ : cast<ExtensionDecl>(dc)->getInherited ());
487+ for (auto index : inherited.getIndices ()) {
488+ if (auto inheritedTy = inherited.getResolvedType (index)) {
489+ if (auto typeWitness = resolveTypeWitnessViaParameterizedProtocol (
490+ inheritedTy, assocType)) {
491+ recordTypeWitness (conformance, assocType, typeWitness, nullptr );
492+ deducedFromParameterizedProtocolType = true ;
493+ }
494+ }
495+ }
496+
497+ // Next, look for a member type declaration with this name.
459498 NLOptions subOptions = (NL_QualifiedDefault | NL_OnlyTypes |
460499 NL_ProtocolMembers | NL_IncludeAttributeImplements);
461500
@@ -562,27 +601,40 @@ static ResolveWitnessResult resolveTypeWitnessViaLookup(
562601 }
563602 }
564603
565- // If there are no viable witnesses, and all nonviable candidates came from
566- // protocol extensions, treat this as "missing".
567- if (viable.empty () &&
568- std::find_if (nonViable.begin (), nonViable.end (),
569- [](const std::pair<TypeDecl *, CheckTypeWitnessResult> &x) {
570- return x.first ->getDeclContext ()
571- ->getSelfProtocolDecl () == nullptr ;
572- }) == nonViable.end ())
573- return ResolveWitnessResult::Missing;
604+ if (!deducedFromParameterizedProtocolType) {
605+ // If there are no viable witnesses, and all nonviable candidates came from
606+ // protocol extensions, treat this as "missing".
607+ if (viable.empty () &&
608+ std::find_if (nonViable.begin (), nonViable.end (),
609+ [](const std::pair<TypeDecl *, CheckTypeWitnessResult> &x) {
610+ return x.first ->getDeclContext ()
611+ ->getSelfProtocolDecl () == nullptr ;
612+ }) == nonViable.end ())
613+ return ResolveWitnessResult::Missing;
614+
615+ // If there is a single viable candidate, form a substitution for it.
616+ if (viable.size () == 1 ) {
617+ auto interfaceType = viable.front ().MemberType ;
618+ recordTypeWitness (conformance, assocType, interfaceType,
619+ viable.front ().Member );
620+ return ResolveWitnessResult::Success;
621+ }
574622
575- // If there is a single viable candidate, form a substitution for it.
576- if (viable.size () == 1 ) {
577- auto interfaceType = viable.front ().MemberType ;
578- recordTypeWitness (conformance, assocType, interfaceType,
579- viable.front ().Member );
580- return ResolveWitnessResult::Success;
581- }
623+ // Record an error.
624+ recordTypeWitness (conformance, assocType,
625+ ErrorType::get (ctx), nullptr );
626+ } else {
627+ // We deduced the type witness from a parameterized protocol type, so just
628+ // make sure there was nothing else.
629+ if (viable.size () == 1 &&
630+ isa<TypeAliasDecl>(viable[0 ].Member ) &&
631+ viable[0 ].Member ->isSynthesized ()) {
632+ // We found the type alias synthesized above.
633+ return ResolveWitnessResult::Success;
634+ }
582635
583- // Record an error.
584- recordTypeWitness (conformance, assocType,
585- ErrorType::get (ctx), nullptr );
636+ // Otherwise fall through.
637+ }
586638
587639 // If we had multiple viable types, diagnose the ambiguity.
588640 if (!viable.empty ()) {
0 commit comments