@@ -467,6 +467,35 @@ static bool matchCallArgumentsImpl(
467
467
return;
468
468
}
469
469
470
+ // Let's consider current closure to be extraneous if:
471
+ //
472
+ // - current parameter has a default value and doesn't accept a trailing
473
+ // closure; and
474
+ // - no other free parameter after this one accepts a trailing closure via
475
+ // forward or backward scan. This check makes sure that it's safe to
476
+ // reject and push it to the next parameter without affecting backward
477
+ // scan logic.
478
+ //
479
+ // In other words - let's push the closure argument through defaulted
480
+ // parameters until it can be considered extraneous if no parameters
481
+ // could possibly match it.
482
+ if (!paramInfo.acceptsUnlabeledTrailingClosureArgument(paramIdx) &&
483
+ !parameterRequiresArgument(params, paramInfo, paramIdx)) {
484
+ if (llvm::none_of(
485
+ range(paramIdx + 1, params.size()), [&](unsigned idx) {
486
+ return parameterBindings[idx].empty() &&
487
+ (paramInfo.acceptsUnlabeledTrailingClosureArgument(
488
+ idx) ||
489
+ backwardScanAcceptsTrailingClosure(params[idx]));
490
+ })) {
491
+ haveUnfulfilledParams = true;
492
+ return;
493
+ }
494
+
495
+ // If one or more parameters can match the closure, let's check
496
+ // whether backward scan is applicable here.
497
+ }
498
+
470
499
// If this parameter does not require an argument, consider applying a
471
500
// backward-match rule that skips this parameter if doing so is the only
472
501
// way to successfully match arguments to parameters.
@@ -1076,8 +1105,10 @@ constraints::getCompletionArgInfo(ASTNode anchor, ConstraintSystem &CS) {
1076
1105
class ArgumentFailureTracker : public MatchCallArgumentListener {
1077
1106
protected:
1078
1107
ConstraintSystem &CS;
1108
+ NullablePtr<ValueDecl> Callee;
1079
1109
SmallVectorImpl<AnyFunctionType::Param> &Arguments;
1080
1110
ArrayRef<AnyFunctionType::Param> Parameters;
1111
+ Optional<unsigned> UnlabeledTrailingClosureArgIndex;
1081
1112
ConstraintLocatorBuilder Locator;
1082
1113
1083
1114
private:
@@ -1109,11 +1140,14 @@ class ArgumentFailureTracker : public MatchCallArgumentListener {
1109
1140
}
1110
1141
1111
1142
public:
1112
- ArgumentFailureTracker(ConstraintSystem &cs,
1143
+ ArgumentFailureTracker(ConstraintSystem &cs, ValueDecl *callee,
1113
1144
SmallVectorImpl<AnyFunctionType::Param> &args,
1114
1145
ArrayRef<AnyFunctionType::Param> params,
1146
+ Optional<unsigned> unlabeledTrailingClosureArgIndex,
1115
1147
ConstraintLocatorBuilder locator)
1116
- : CS(cs), Arguments(args), Parameters(params), Locator(locator) {}
1148
+ : CS(cs), Callee(callee), Arguments(args), Parameters(params),
1149
+ UnlabeledTrailingClosureArgIndex(unlabeledTrailingClosureArgIndex),
1150
+ Locator(locator) {}
1117
1151
1118
1152
~ArgumentFailureTracker() override {
1119
1153
if (!MissingArguments.empty()) {
@@ -1143,6 +1177,19 @@ class ArgumentFailureTracker : public MatchCallArgumentListener {
1143
1177
if (!CS.shouldAttemptFixes())
1144
1178
return true;
1145
1179
1180
+ // If this is a trailing closure, let's check if the call is
1181
+ // to an init of a callable type. If so, let's not record it
1182
+ // as extraneous since it would be matched against implicitly
1183
+ // injected `.callAsFunction` call.
1184
+ if (UnlabeledTrailingClosureArgIndex &&
1185
+ argIdx == *UnlabeledTrailingClosureArgIndex && Callee) {
1186
+ if (auto *ctor = dyn_cast<ConstructorDecl>(Callee.get())) {
1187
+ auto resultTy = ctor->getResultInterfaceType();
1188
+ if (resultTy->isCallableNominalType(CS.DC))
1189
+ return true;
1190
+ }
1191
+ }
1192
+
1146
1193
ExtraArguments.push_back(std::make_pair(argIdx, Arguments[argIdx]));
1147
1194
return false;
1148
1195
}
@@ -1251,12 +1298,15 @@ class CompletionArgumentTracker : public ArgumentFailureTracker {
1251
1298
struct CompletionArgInfo ArgInfo;
1252
1299
1253
1300
public:
1254
- CompletionArgumentTracker(ConstraintSystem &cs,
1301
+ CompletionArgumentTracker(ConstraintSystem &cs, ValueDecl *callee,
1255
1302
SmallVectorImpl<AnyFunctionType::Param> &args,
1256
1303
ArrayRef<AnyFunctionType::Param> params,
1304
+ Optional<unsigned> unlabeledTrailingClosureArgIndex,
1257
1305
ConstraintLocatorBuilder locator,
1258
1306
struct CompletionArgInfo ArgInfo)
1259
- : ArgumentFailureTracker(cs, args, params, locator), ArgInfo(ArgInfo) {}
1307
+ : ArgumentFailureTracker(cs, callee, args, params,
1308
+ unlabeledTrailingClosureArgIndex, locator),
1309
+ ArgInfo(ArgInfo) {}
1260
1310
1261
1311
Optional<unsigned> missingArgument(unsigned paramIdx,
1262
1312
unsigned argInsertIdx) override {
@@ -1666,14 +1716,16 @@ static ConstraintSystem::TypeMatchResult matchCallArguments(
1666
1716
if (cs.isForCodeCompletion()) {
1667
1717
if (auto completionInfo = getCompletionArgInfo(locator.getAnchor(), cs)) {
1668
1718
listener = std::make_unique<CompletionArgumentTracker>(
1669
- cs, argsWithLabels, params, locator, *completionInfo);
1719
+ cs, callee, argsWithLabels, params,
1720
+ argList->getFirstTrailingClosureIndex(), locator, *completionInfo);
1670
1721
}
1671
1722
}
1672
1723
if (!listener) {
1673
1724
// We didn't create an argument tracker for code completion. Create a
1674
1725
// normal one.
1675
- listener = std::make_unique<ArgumentFailureTracker>(cs, argsWithLabels,
1676
- params, locator);
1726
+ listener = std::make_unique<ArgumentFailureTracker>(
1727
+ cs, callee, argsWithLabels, params,
1728
+ argList->getFirstTrailingClosureIndex(), locator);
1677
1729
}
1678
1730
auto callArgumentMatch = constraints::matchCallArguments(
1679
1731
argsWithLabels, params, paramInfo,
0 commit comments