@@ -430,17 +430,37 @@ 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
+ const auto ¶m = params[numParams - 1 ];
434
+ //
435
+ bool isExtraClosure = false ;
433
436
// If there is no suitable last parameter to accept the trailing closure,
434
437
// notify the listener and bail if we need to.
435
- if (!acceptsTrailingClosure (params[numParams - 1 ])) {
436
- if (listener.trailingClosureMismatch (numParams - 1 , numArgs - 1 ))
438
+ if (!acceptsTrailingClosure (param)) {
439
+ if (numArgs > numParams) {
440
+ // Argument before the trailing closure.
441
+ unsigned prevArg = numArgs - 2 ;
442
+ auto &arg = args[prevArg];
443
+ // If the argument before trailing closure matches
444
+ // last parameter, this is just a special case of
445
+ // an extraneous argument.
446
+ if (param.hasLabel () && param.getLabel () == arg.getLabel ()) {
447
+ isExtraClosure = true ;
448
+ if (listener.extraArgument (numArgs - 1 ))
449
+ return true ;
450
+ }
451
+ }
452
+
453
+ if (!isExtraClosure &&
454
+ listener.trailingClosureMismatch (numParams - 1 , numArgs - 1 ))
437
455
return true ;
438
456
}
439
457
440
458
// Claim the parameter/argument pair.
441
459
claimedArgs[numArgs-1 ] = true ;
442
460
++numClaimedArgs;
443
- parameterBindings[numParams-1 ].push_back (numArgs-1 );
461
+ // Let's claim the trailing closure unless it's an extra argument.
462
+ if (!isExtraClosure)
463
+ parameterBindings[numParams - 1 ].push_back (numArgs - 1 );
444
464
}
445
465
446
466
// Mark through the parameters, binding them to their arguments.
@@ -923,6 +943,27 @@ class ArgumentFailureTracker : public MatchCallArgumentListener {
923
943
return false ;
924
944
}
925
945
946
+ bool trailingClosureMismatch (unsigned paramIdx, unsigned argIdx) override {
947
+ if (!CS.shouldAttemptFixes ())
948
+ return true ;
949
+
950
+ auto argType = Arguments[argIdx].getPlainType ();
951
+ argType.visit ([&](Type type) {
952
+ if (auto *typeVar = type->getAs <TypeVariableType>())
953
+ CS.recordHole (typeVar);
954
+ });
955
+
956
+ const auto ¶m = Parameters[paramIdx];
957
+
958
+ auto *argLoc = CS.getConstraintLocator (
959
+ Locator.withPathElement (LocatorPathElt::ApplyArgToParam (
960
+ argIdx, paramIdx, param.getParameterFlags ())));
961
+
962
+ auto *fix = AllowInvalidUseOfTrailingClosure::create (
963
+ CS, argType, param.getPlainType (), argLoc);
964
+ return CS.recordFix (fix, /* impact=*/ 3 );
965
+ }
966
+
926
967
ArrayRef<std::pair<unsigned , AnyFunctionType::Param>>
927
968
getExtraneousArguments () const {
928
969
return ExtraArguments;
@@ -2696,6 +2737,10 @@ bool ConstraintSystem::repairFailures(
2696
2737
2697
2738
case ConstraintLocator::ApplyArgToParam: {
2698
2739
auto loc = getConstraintLocator (locator);
2740
+
2741
+ if (hasFixFor (loc, FixKind::AllowInvalidUseOfTrailingClosure))
2742
+ return true ;
2743
+
2699
2744
if (repairByInsertingExplicitCall (lhs, rhs))
2700
2745
break ;
2701
2746
@@ -8054,6 +8099,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
8054
8099
case FixKind::GenericArgumentsMismatch:
8055
8100
case FixKind::AllowMutatingMemberOnRValueBase:
8056
8101
case FixKind::AllowTupleSplatForSingleParameter:
8102
+ case FixKind::AllowInvalidUseOfTrailingClosure:
8057
8103
llvm_unreachable (" handled elsewhere" );
8058
8104
}
8059
8105
0 commit comments