@@ -555,11 +555,9 @@ static void determineBestChoicesInContext(
555555 // Check protocol requirement(s) if this parameter is a
556556 // generic parameter type.
557557 if (genericSig && paramType->isTypeParameter ()) {
558- // If candidate is not fully resolved or is matched against a
559- // dependent member type (i.e. `Self.T`), let's check conformances
560- // only and lower the score.
561- if (candidateType->hasTypeVariable () ||
562- paramType->is <DependentMemberType>()) {
558+ // Light-weight check if cases where `checkRequirements` is not
559+ // applicable.
560+ auto checkProtocolRequirementsOnly = [&]() -> double {
563561 auto protocolRequirements =
564562 genericSig->getRequiredProtocols (paramType);
565563 if (llvm::all_of (protocolRequirements, [&](ProtocolDecl *protocol) {
@@ -574,29 +572,64 @@ static void determineBestChoicesInContext(
574572 }
575573
576574 return 0 ;
575+ };
576+
577+ // If candidate is not fully resolved or is matched against a
578+ // dependent member type (i.e. `Self.T`), let's check conformances
579+ // only and lower the score.
580+ if (candidateType->hasTypeVariable () ||
581+ paramType->is <DependentMemberType>()) {
582+ return checkProtocolRequirementsOnly ();
577583 }
578584
579585 // Cannot match anything but generic type parameters here.
580586 if (!paramType->is <GenericTypeParamType>())
581587 return std::nullopt ;
582588
583- // If the candidate type is fully resolved, let's check all of
584- // the requirements that are associated with the corresponding
585- // parameter, if all of them are satisfied this candidate is
586- // an exact match.
587-
588- auto isParameterType = [¶mType](Type type) {
589- return type->isEqual (paramType);
590- };
591-
589+ bool hasUnsatisfiableRequirements = false ;
592590 SmallVector<Requirement, 4 > requirements;
591+
593592 for (const auto &requirement : genericSig.getRequirements ()) {
594- if (requirement.getFirstType ().findIf (isParameterType) ||
595- (requirement.getKind () != RequirementKind::Layout &&
596- requirement.getSecondType ().findIf (isParameterType)))
593+ if (hasUnsatisfiableRequirements)
594+ break ;
595+
596+ llvm::SmallPtrSet<GenericTypeParamType *, 2 > toExamine;
597+
598+ auto recordReferencesGenericParams = [&toExamine](Type type) {
599+ type.visit ([&toExamine](Type innerTy) {
600+ if (auto *GP = innerTy->getAs <GenericTypeParamType>())
601+ toExamine.insert (GP);
602+ });
603+ };
604+
605+ recordReferencesGenericParams (requirement.getFirstType ());
606+
607+ if (requirement.getKind () != RequirementKind::Layout)
608+ recordReferencesGenericParams (requirement.getSecondType ());
609+
610+ if (llvm::any_of (toExamine, [&](GenericTypeParamType *GP) {
611+ return paramType->isEqual (GP);
612+ })) {
597613 requirements.push_back (requirement);
614+ // If requirement mentions other generic parameters
615+ // `checkRequirements` would because we don't have
616+ // candidate substitutions for anything but the current
617+ // parameter type.
618+ hasUnsatisfiableRequirements |= toExamine.size () > 1 ;
619+ }
598620 }
599621
622+ // If some of the requirements cannot be satisfied, because
623+ // they reference other generic parameters, for example:
624+ // `<T, U, where T.Element == U.Element>`, let's perform a
625+ // light-weight check instead of skipping this overload choice.
626+ if (hasUnsatisfiableRequirements)
627+ return checkProtocolRequirementsOnly ();
628+
629+ // If the candidate type is fully resolved, let's check all of
630+ // the requirements that are associated with the corresponding
631+ // parameter, if all of them are satisfied this candidate is
632+ // an exact match.
600633 auto result = checkRequirements (
601634 requirements,
602635 [¶mType, &candidateType](SubstitutableType *type) -> Type {
0 commit comments