@@ -430,17 +430,56 @@ matchCallArguments(SmallVectorImpl<AnyFunctionType::Param> &args,
430
430
431
431
// If we have a trailing closure, it maps to the last parameter.
432
432
if (hasTrailingClosure && numParams > 0 ) {
433
+ unsigned lastParamIdx = numParams - 1 ;
434
+ bool lastAcceptsTrailingClosure =
435
+ acceptsTrailingClosure (params[lastParamIdx]);
436
+
437
+ // If the last parameter is defaulted, this might be
438
+ // an attempt to use a trailing closure with previous
439
+ // parameter that accepts a function type e.g.
440
+ //
441
+ // func foo(_: () -> Int, _ x: Int = 0) {}
442
+ // foo { 42 }
443
+ if (!lastAcceptsTrailingClosure && numParams > 1 &&
444
+ paramInfo.hasDefaultArgument (lastParamIdx)) {
445
+ auto paramType = params[lastParamIdx - 1 ].getPlainType ();
446
+ // If the parameter before defaulted last accepts.
447
+ if (paramType->is <AnyFunctionType>()) {
448
+ lastAcceptsTrailingClosure = true ;
449
+ lastParamIdx -= 1 ;
450
+ }
451
+ }
452
+
453
+ bool isExtraClosure = false ;
433
454
// If there is no suitable last parameter to accept the trailing closure,
434
455
// notify the listener and bail if we need to.
435
- if (!acceptsTrailingClosure (params[numParams - 1 ])) {
436
- if (listener.trailingClosureMismatch (numParams - 1 , numArgs - 1 ))
456
+ if (!lastAcceptsTrailingClosure) {
457
+ if (numArgs > numParams) {
458
+ // Argument before the trailing closure.
459
+ unsigned prevArg = numArgs - 2 ;
460
+ auto &arg = args[prevArg];
461
+ // If the argument before trailing closure matches
462
+ // last parameter, this is just a special case of
463
+ // an extraneous argument.
464
+ const auto param = params[numParams - 1 ];
465
+ if (param.hasLabel () && param.getLabel () == arg.getLabel ()) {
466
+ isExtraClosure = true ;
467
+ if (listener.extraArgument (numArgs - 1 ))
468
+ return true ;
469
+ }
470
+ }
471
+
472
+ if (!isExtraClosure &&
473
+ listener.trailingClosureMismatch (lastParamIdx, numArgs - 1 ))
437
474
return true ;
438
475
}
439
476
440
477
// Claim the parameter/argument pair.
441
478
claimedArgs[numArgs-1 ] = true ;
442
479
++numClaimedArgs;
443
- parameterBindings[numParams-1 ].push_back (numArgs-1 );
480
+ // Let's claim the trailing closure unless it's an extra argument.
481
+ if (!isExtraClosure)
482
+ parameterBindings[lastParamIdx].push_back (numArgs - 1 );
444
483
}
445
484
446
485
// Mark through the parameters, binding them to their arguments.
@@ -923,6 +962,27 @@ class ArgumentFailureTracker : public MatchCallArgumentListener {
923
962
return false ;
924
963
}
925
964
965
+ bool trailingClosureMismatch (unsigned paramIdx, unsigned argIdx) override {
966
+ if (!CS.shouldAttemptFixes ())
967
+ return true ;
968
+
969
+ auto argType = Arguments[argIdx].getPlainType ();
970
+ argType.visit ([&](Type type) {
971
+ if (auto *typeVar = type->getAs <TypeVariableType>())
972
+ CS.recordHole (typeVar);
973
+ });
974
+
975
+ const auto ¶m = Parameters[paramIdx];
976
+
977
+ auto *argLoc = CS.getConstraintLocator (
978
+ Locator.withPathElement (LocatorPathElt::ApplyArgToParam (
979
+ argIdx, paramIdx, param.getParameterFlags ())));
980
+
981
+ auto *fix = AllowInvalidUseOfTrailingClosure::create (
982
+ CS, argType, param.getPlainType (), argLoc);
983
+ return CS.recordFix (fix, /* impact=*/ 3 );
984
+ }
985
+
926
986
ArrayRef<std::pair<unsigned , AnyFunctionType::Param>>
927
987
getExtraneousArguments () const {
928
988
return ExtraArguments;
@@ -2696,6 +2756,10 @@ bool ConstraintSystem::repairFailures(
2696
2756
2697
2757
case ConstraintLocator::ApplyArgToParam: {
2698
2758
auto loc = getConstraintLocator (locator);
2759
+
2760
+ if (hasFixFor (loc, FixKind::AllowInvalidUseOfTrailingClosure))
2761
+ return true ;
2762
+
2699
2763
if (repairByInsertingExplicitCall (lhs, rhs))
2700
2764
break ;
2701
2765
@@ -8054,6 +8118,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
8054
8118
case FixKind::GenericArgumentsMismatch:
8055
8119
case FixKind::AllowMutatingMemberOnRValueBase:
8056
8120
case FixKind::AllowTupleSplatForSingleParameter:
8121
+ case FixKind::AllowInvalidUseOfTrailingClosure:
8057
8122
llvm_unreachable (" handled elsewhere" );
8058
8123
}
8059
8124
0 commit comments