@@ -567,6 +567,7 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
567
567
568
568
// Construct a constraint system to compare the two declarations.
569
569
ConstraintSystem cs (tc, dc, ConstraintSystemOptions ());
570
+ bool knownNonSubtype = false ;
570
571
571
572
auto locator = cs.getConstraintLocator (nullptr );
572
573
// FIXME: Locator when anchored on a declaration.
@@ -683,6 +684,35 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
683
684
unsigned numParams2 = params2.size ();
684
685
if (numParams1 > numParams2) return false ;
685
686
687
+ // If they both have trailing closures, compare those separately.
688
+ bool compareTrailingClosureParamsSeparately = false ;
689
+ if (!tc.getLangOpts ().isSwiftVersion3 ()) {
690
+ if (numParams1 > 0 && numParams2 > 0 &&
691
+ params1.back ().Ty ->is <AnyFunctionType>() &&
692
+ params2.back ().Ty ->is <AnyFunctionType>()) {
693
+ compareTrailingClosureParamsSeparately = true ;
694
+ --numParams1;
695
+ --numParams2;
696
+ }
697
+ }
698
+
699
+ auto maybeAddSubtypeConstraint =
700
+ [&](const CallArgParam ¶m1, const CallArgParam ¶m2) -> bool {
701
+ // If one parameter is variadic and the other is not...
702
+ if (param1.isVariadic () != param2.isVariadic ()) {
703
+ // If the first parameter is the variadic one, it's not
704
+ // more specialized.
705
+ if (param1.isVariadic ()) return false ;
706
+
707
+ fewerEffectiveParameters = true ;
708
+ }
709
+
710
+ // Check whether the first parameter is a subtype of the second.
711
+ cs.addConstraint (ConstraintKind::Subtype, param1.Ty , param2.Ty ,
712
+ locator);
713
+ return true ;
714
+ };
715
+
686
716
for (unsigned i = 0 ; i != numParams2; ++i) {
687
717
// If there is no corresponding argument in the first
688
718
// parameter list...
@@ -698,30 +728,26 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
698
728
continue ;
699
729
}
700
730
701
- // If one parameter is variadic and the other is not...
702
- if (params1[i].isVariadic () != params2[i].isVariadic ()) {
703
- // If the first parameter is the variadic one, it's not
704
- // more specialized.
705
- if (params1[i].isVariadic ()) return false ;
706
-
707
- fewerEffectiveParameters = true ;
708
- }
709
-
710
- // Check whether the first parameter is a subtype of the second.
711
- cs.addConstraint (ConstraintKind::Subtype,
712
- params1[i].Ty , params2[i].Ty , locator);
731
+ if (!maybeAddSubtypeConstraint (params1[i], params2[i]))
732
+ return false ;
713
733
}
714
734
735
+ if (compareTrailingClosureParamsSeparately)
736
+ if (!maybeAddSubtypeConstraint (params1.back (), params2.back ()))
737
+ knownNonSubtype = true ;
738
+
715
739
break ;
716
740
}
717
741
}
718
742
719
- // Solve the system.
720
- auto solution = cs.solveSingle (FreeTypeVariableBinding::Allow);
743
+ if (!knownNonSubtype) {
744
+ // Solve the system.
745
+ auto solution = cs.solveSingle (FreeTypeVariableBinding::Allow);
721
746
722
- // Ban value-to-optional conversions.
723
- if (solution && solution->getFixedScore ().Data [SK_ValueToOptional] == 0 )
724
- return true ;
747
+ // Ban value-to-optional conversions.
748
+ if (solution && solution->getFixedScore ().Data [SK_ValueToOptional] == 0 )
749
+ return true ;
750
+ }
725
751
726
752
// If the first function has fewer effective parameters than the
727
753
// second, it is more specialized.
0 commit comments