Skip to content

Commit b6494f6

Browse files
authored
Merge pull request #4785 from jrose-apple/trailing-closures-and-default-arguments
When ranking overloads, always match up final closure parameters.
2 parents 5d185d1 + 27b4070 commit b6494f6

File tree

3 files changed

+519
-18
lines changed

3 files changed

+519
-18
lines changed

lib/Sema/CSRanking.cpp

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
567567

568568
// Construct a constraint system to compare the two declarations.
569569
ConstraintSystem cs(tc, dc, ConstraintSystemOptions());
570+
bool knownNonSubtype = false;
570571

571572
auto locator = cs.getConstraintLocator(nullptr);
572573
// FIXME: Locator when anchored on a declaration.
@@ -683,6 +684,35 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
683684
unsigned numParams2 = params2.size();
684685
if (numParams1 > numParams2) return false;
685686

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 &param1, const CallArgParam &param2) -> 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+
686716
for (unsigned i = 0; i != numParams2; ++i) {
687717
// If there is no corresponding argument in the first
688718
// parameter list...
@@ -698,30 +728,26 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
698728
continue;
699729
}
700730

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;
713733
}
714734

735+
if (compareTrailingClosureParamsSeparately)
736+
if (!maybeAddSubtypeConstraint(params1.back(), params2.back()))
737+
knownNonSubtype = true;
738+
715739
break;
716740
}
717741
}
718742

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);
721746

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+
}
725751

726752
// If the first function has fewer effective parameters than the
727753
// second, it is more specialized.

0 commit comments

Comments
 (0)