@@ -439,6 +439,28 @@ static bool isAsyncSequenceFailure(AssociatedTypeDecl *assocType) {
439
439
return assocType->getName () == assocType->getASTContext ().Id_Failure ;
440
440
}
441
441
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
+
442
464
// / Attempt to resolve a type witness via member name lookup.
443
465
static ResolveWitnessResult resolveTypeWitnessViaLookup (
444
466
NormalProtocolConformance *conformance,
@@ -456,6 +478,23 @@ static ResolveWitnessResult resolveTypeWitnessViaLookup(
456
478
});
457
479
}
458
480
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.
459
498
NLOptions subOptions = (NL_QualifiedDefault | NL_OnlyTypes |
460
499
NL_ProtocolMembers | NL_IncludeAttributeImplements);
461
500
@@ -562,27 +601,40 @@ static ResolveWitnessResult resolveTypeWitnessViaLookup(
562
601
}
563
602
}
564
603
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
+ }
574
622
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
+ }
582
635
583
- // Record an error.
584
- recordTypeWitness (conformance, assocType,
585
- ErrorType::get (ctx), nullptr );
636
+ // Otherwise fall through.
637
+ }
586
638
587
639
// If we had multiple viable types, diagnose the ambiguity.
588
640
if (!viable.empty ()) {
0 commit comments