@@ -467,6 +467,35 @@ static bool matchCallArgumentsImpl(
467467 return;
468468 }
469469
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+
470499 // If this parameter does not require an argument, consider applying a
471500 // backward-match rule that skips this parameter if doing so is the only
472501 // way to successfully match arguments to parameters.
@@ -1076,8 +1105,10 @@ constraints::getCompletionArgInfo(ASTNode anchor, ConstraintSystem &CS) {
10761105class ArgumentFailureTracker : public MatchCallArgumentListener {
10771106protected:
10781107 ConstraintSystem &CS;
1108+ NullablePtr<ValueDecl> Callee;
10791109 SmallVectorImpl<AnyFunctionType::Param> &Arguments;
10801110 ArrayRef<AnyFunctionType::Param> Parameters;
1111+ Optional<unsigned> UnlabeledTrailingClosureArgIndex;
10811112 ConstraintLocatorBuilder Locator;
10821113
10831114private:
@@ -1109,11 +1140,14 @@ class ArgumentFailureTracker : public MatchCallArgumentListener {
11091140 }
11101141
11111142public:
1112- ArgumentFailureTracker(ConstraintSystem &cs,
1143+ ArgumentFailureTracker(ConstraintSystem &cs, ValueDecl *callee,
11131144 SmallVectorImpl<AnyFunctionType::Param> &args,
11141145 ArrayRef<AnyFunctionType::Param> params,
1146+ Optional<unsigned> unlabeledTrailingClosureArgIndex,
11151147 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) {}
11171151
11181152 ~ArgumentFailureTracker() override {
11191153 if (!MissingArguments.empty()) {
@@ -1143,6 +1177,19 @@ class ArgumentFailureTracker : public MatchCallArgumentListener {
11431177 if (!CS.shouldAttemptFixes())
11441178 return true;
11451179
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+
11461193 ExtraArguments.push_back(std::make_pair(argIdx, Arguments[argIdx]));
11471194 return false;
11481195 }
@@ -1251,12 +1298,15 @@ class CompletionArgumentTracker : public ArgumentFailureTracker {
12511298 struct CompletionArgInfo ArgInfo;
12521299
12531300public:
1254- CompletionArgumentTracker(ConstraintSystem &cs,
1301+ CompletionArgumentTracker(ConstraintSystem &cs, ValueDecl *callee,
12551302 SmallVectorImpl<AnyFunctionType::Param> &args,
12561303 ArrayRef<AnyFunctionType::Param> params,
1304+ Optional<unsigned> unlabeledTrailingClosureArgIndex,
12571305 ConstraintLocatorBuilder locator,
12581306 struct CompletionArgInfo ArgInfo)
1259- : ArgumentFailureTracker(cs, args, params, locator), ArgInfo(ArgInfo) {}
1307+ : ArgumentFailureTracker(cs, callee, args, params,
1308+ unlabeledTrailingClosureArgIndex, locator),
1309+ ArgInfo(ArgInfo) {}
12601310
12611311 Optional<unsigned> missingArgument(unsigned paramIdx,
12621312 unsigned argInsertIdx) override {
@@ -1666,14 +1716,16 @@ static ConstraintSystem::TypeMatchResult matchCallArguments(
16661716 if (cs.isForCodeCompletion()) {
16671717 if (auto completionInfo = getCompletionArgInfo(locator.getAnchor(), cs)) {
16681718 listener = std::make_unique<CompletionArgumentTracker>(
1669- cs, argsWithLabels, params, locator, *completionInfo);
1719+ cs, callee, argsWithLabels, params,
1720+ argList->getFirstTrailingClosureIndex(), locator, *completionInfo);
16701721 }
16711722 }
16721723 if (!listener) {
16731724 // We didn't create an argument tracker for code completion. Create a
16741725 // 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);
16771729 }
16781730 auto callArgumentMatch = constraints::matchCallArguments(
16791731 argsWithLabels, params, paramInfo,
0 commit comments