@@ -567,75 +567,126 @@ bool CompareDeclSpecializationRequest::evaluate(
567567 auto params1 = funcTy1->getParams ();
568568 auto params2 = funcTy2->getParams ();
569569
570- unsigned numParams1 = params1.size ();
571- unsigned numParams2 = params2.size ();
572- if (numParams1 > numParams2)
573- return completeResult (false );
574-
575- // If they both have trailing closures, compare those separately.
576- bool compareTrailingClosureParamsSeparately = false ;
577- if (numParams1 > 0 && numParams2 > 0 &&
578- params1.back ().getParameterType ()->is <AnyFunctionType>() &&
579- params2.back ().getParameterType ()->is <AnyFunctionType>()) {
580- compareTrailingClosureParamsSeparately = true ;
581- }
570+ // TODO: We should consider merging these two branches together in
571+ // the future instead of re-implementing `matchCallArguments`.
572+ if (containsPackExpansionType (params1) ||
573+ containsPackExpansionType (params2)) {
574+ ParameterListInfo paramListInfo (params2, decl2, decl2->hasCurriedSelf ());
575+
576+ MatchCallArgumentListener listener;
577+ SmallVector<AnyFunctionType::Param> args (params1);
578+ auto matching = matchCallArguments (
579+ args, params2, paramListInfo, llvm::None,
580+ /* allowFixes=*/ false , listener, TrailingClosureMatching::Forward);
581+
582+ if (!matching)
583+ return completeResult (false );
584+
585+ for (unsigned paramIdx = 0 ,
586+ numParams = matching->parameterBindings .size ();
587+ paramIdx != numParams; ++paramIdx) {
588+ const auto ¶m = params2[paramIdx];
589+ auto paramTy = param.getOldType ();
590+
591+ if (paramListInfo.isVariadicGenericParameter (paramIdx) &&
592+ isPackExpansionType (paramTy)) {
593+ SmallVector<Type, 2 > argTypes;
594+ for (auto argIdx : matching->parameterBindings [paramIdx]) {
595+ // Don't prefer `T...` over `repeat each T`.
596+ if (args[argIdx].isVariadic ())
597+ return completeResult (false );
598+ argTypes.push_back (args[argIdx].getPlainType ());
599+ }
582600
583- auto maybeAddSubtypeConstraint =
584- [&](const AnyFunctionType::Param ¶m1,
585- const AnyFunctionType::Param ¶m2) -> bool {
586- // If one parameter is variadic and the other is not...
587- if (param1.isVariadic () != param2.isVariadic ()) {
588- // If the first parameter is the variadic one, it's not
589- // more specialized.
590- if (param1.isVariadic ())
591- return false ;
601+ auto *argPack = PackType::get (cs.getASTContext (), argTypes);
602+ cs.addConstraint (ConstraintKind::Subtype,
603+ PackExpansionType::get (argPack, argPack), paramTy,
604+ locator);
605+ continue ;
606+ }
607+
608+ for (auto argIdx : matching->parameterBindings [paramIdx]) {
609+ const auto &arg = args[argIdx];
610+ // Always prefer non-variadic version when possible.
611+ if (arg.isVariadic ())
612+ return completeResult (false );
592613
593- fewerEffectiveParameters = true ;
614+ cs.addConstraint (ConstraintKind::Subtype, arg.getOldType (),
615+ paramTy, locator);
616+ }
617+ }
618+ } else {
619+ unsigned numParams1 = params1.size ();
620+ unsigned numParams2 = params2.size ();
621+
622+ if (numParams1 > numParams2)
623+ return completeResult (false );
624+
625+ // If they both have trailing closures, compare those separately.
626+ bool compareTrailingClosureParamsSeparately = false ;
627+ if (numParams1 > 0 && numParams2 > 0 &&
628+ params1.back ().getParameterType ()->is <AnyFunctionType>() &&
629+ params2.back ().getParameterType ()->is <AnyFunctionType>()) {
630+ compareTrailingClosureParamsSeparately = true ;
594631 }
595632
596- Type paramType1 = getAdjustedParamType (param1);
597- Type paramType2 = getAdjustedParamType (param2);
633+ auto maybeAddSubtypeConstraint =
634+ [&](const AnyFunctionType::Param ¶m1,
635+ const AnyFunctionType::Param ¶m2) -> bool {
636+ // If one parameter is variadic and the other is not...
637+ if (param1.isVariadic () != param2.isVariadic ()) {
638+ // If the first parameter is the variadic one, it's not
639+ // more specialized.
640+ if (param1.isVariadic ())
641+ return false ;
642+
643+ fewerEffectiveParameters = true ;
644+ }
598645
599- // Check whether the first parameter is a subtype of the second.
600- cs.addConstraint (ConstraintKind::Subtype, paramType1, paramType2,
601- locator);
602- return true ;
603- };
604-
605- auto pairMatcher = [&](unsigned idx1, unsigned idx2) -> bool {
606- // Emulate behavior from when IUO was a type, where IUOs
607- // were considered subtypes of plain optionals, but not
608- // vice-versa. This wouldn't normally happen, but there are
609- // cases where we can rename imported APIs so that we have a
610- // name collision, and where the parameter type(s) are the
611- // same except for details of the kind of optional declared.
612- auto param1IsIUO = paramIsIUO (decl1, idx1);
613- auto param2IsIUO = paramIsIUO (decl2, idx2);
614- if (param2IsIUO && !param1IsIUO)
615- return false ;
616-
617- if (!maybeAddSubtypeConstraint (params1[idx1], params2[idx2]))
618- return false ;
646+ Type paramType1 = getAdjustedParamType (param1);
647+ Type paramType2 = getAdjustedParamType (param2);
619648
620- return true ;
621- };
649+ // Check whether the first parameter is a subtype of the second.
650+ cs.addConstraint (ConstraintKind::Subtype, paramType1, paramType2,
651+ locator);
652+ return true ;
653+ };
622654
623- ParameterListInfo paramInfo (params2, decl2, decl2->hasCurriedSelf ());
624- auto params2ForMatching = params2;
625- if (compareTrailingClosureParamsSeparately) {
626- --numParams1;
627- params2ForMatching = params2.drop_back ();
628- }
655+ auto pairMatcher = [&](unsigned idx1, unsigned idx2) -> bool {
656+ // Emulate behavior from when IUO was a type, where IUOs
657+ // were considered subtypes of plain optionals, but not
658+ // vice-versa. This wouldn't normally happen, but there are
659+ // cases where we can rename imported APIs so that we have a
660+ // name collision, and where the parameter type(s) are the
661+ // same except for details of the kind of optional declared.
662+ auto param1IsIUO = paramIsIUO (decl1, idx1);
663+ auto param2IsIUO = paramIsIUO (decl2, idx2);
664+ if (param2IsIUO && !param1IsIUO)
665+ return false ;
666+
667+ if (!maybeAddSubtypeConstraint (params1[idx1], params2[idx2]))
668+ return false ;
629669
630- InputMatcher IM (params2ForMatching, paramInfo);
631- if (IM.match (numParams1, pairMatcher) != InputMatcher::IM_Succeeded)
632- return completeResult (false );
670+ return true ;
671+ };
672+
673+ ParameterListInfo paramInfo (params2, decl2, decl2->hasCurriedSelf ());
674+ auto params2ForMatching = params2;
675+ if (compareTrailingClosureParamsSeparately) {
676+ --numParams1;
677+ params2ForMatching = params2.drop_back ();
678+ }
679+
680+ InputMatcher IM (params2ForMatching, paramInfo);
681+ if (IM.match (numParams1, pairMatcher) != InputMatcher::IM_Succeeded)
682+ return completeResult (false );
633683
634- fewerEffectiveParameters |= (IM.getNumSkippedParameters () != 0 );
684+ fewerEffectiveParameters |= (IM.getNumSkippedParameters () != 0 );
635685
636- if (compareTrailingClosureParamsSeparately)
637- if (!maybeAddSubtypeConstraint (params1.back (), params2.back ()))
638- knownNonSubtype = true ;
686+ if (compareTrailingClosureParamsSeparately)
687+ if (!maybeAddSubtypeConstraint (params1.back (), params2.back ()))
688+ knownNonSubtype = true ;
689+ }
639690 }
640691
641692 if (!knownNonSubtype) {
0 commit comments