Skip to content

Commit 495f14a

Browse files
committed
[ConstraintSystem] Use new trailing closure fix in matchCallArguments
1 parent 6bb659c commit 495f14a

File tree

3 files changed

+66
-11
lines changed

3 files changed

+66
-11
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -430,17 +430,37 @@ matchCallArguments(SmallVectorImpl<AnyFunctionType::Param> &args,
430430

431431
// If we have a trailing closure, it maps to the last parameter.
432432
if (hasTrailingClosure && numParams > 0) {
433+
const auto &param = params[numParams - 1];
434+
//
435+
bool isExtraClosure = false;
433436
// If there is no suitable last parameter to accept the trailing closure,
434437
// 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))
437455
return true;
438456
}
439457

440458
// Claim the parameter/argument pair.
441459
claimedArgs[numArgs-1] = true;
442460
++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);
444464
}
445465

446466
// Mark through the parameters, binding them to their arguments.
@@ -923,6 +943,27 @@ class ArgumentFailureTracker : public MatchCallArgumentListener {
923943
return false;
924944
}
925945

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 &param = 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+
926967
ArrayRef<std::pair<unsigned, AnyFunctionType::Param>>
927968
getExtraneousArguments() const {
928969
return ExtraArguments;
@@ -2696,6 +2737,10 @@ bool ConstraintSystem::repairFailures(
26962737

26972738
case ConstraintLocator::ApplyArgToParam: {
26982739
auto loc = getConstraintLocator(locator);
2740+
2741+
if (hasFixFor(loc, FixKind::AllowInvalidUseOfTrailingClosure))
2742+
return true;
2743+
26992744
if (repairByInsertingExplicitCall(lhs, rhs))
27002745
break;
27012746

@@ -8054,6 +8099,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
80548099
case FixKind::GenericArgumentsMismatch:
80558100
case FixKind::AllowMutatingMemberOnRValueBase:
80568101
case FixKind::AllowTupleSplatForSingleParameter:
8102+
case FixKind::AllowInvalidUseOfTrailingClosure:
80578103
llvm_unreachable("handled elsewhere");
80588104
}
80598105

test/Constraints/diag_missing_arg.swift

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,28 @@ trailingClosureSingle1 { 1 } // expected-error {{missing argument for parameter
3434
trailingClosureSingle1() { 1 } // expected-error {{missing argument for parameter 'x' in call}} {{24-24=x: <#Int#>}}
3535

3636
func trailingClosureSingle2(x: () -> Int, y: Int) {} // expected-note * {{here}}
37-
trailingClosureSingle2 { 1 } // expected-error {{trailing closure passed to parameter of type 'Int' that does not accept a closure}}
38-
trailingClosureSingle2() { 1 } // expected-error {{trailing closure passed to parameter of type 'Int' that does not accept a closure}}
37+
trailingClosureSingle2 { 1 }
38+
// expected-error@-1 {{missing argument for parameter 'x' in call}} {{23-23=(x: <#() -> Int#>)}}
39+
// expected-error@-2 {{trailing closure passed to parameter of type 'Int' that does not accept a closure}}
40+
trailingClosureSingle2() { 1 }
41+
// expected-error@-1 {{missing argument for parameter 'x' in call}} {{24-24=x: <#() -> Int#>}}
42+
// expected-error@-2 {{trailing closure passed to parameter of type 'Int' that does not accept a closure}}
3943

4044
func trailingClosureMulti1(x: Int, y: Int, z: () -> Int) {} // expected-note * {{here}}
4145
trailingClosureMulti1(y: 1) { 1 } // expected-error {{missing argument for parameter 'x' in call}} {{23-23=x: <#Int#>, }}
4246
trailingClosureMulti1(x: 1) { 1 } // expected-error {{missing argument for parameter 'y' in call}} {{27-27=, y: <#Int#>}}
4347
trailingClosureMulti1(x: 1, y: 1) // expected-error {{missing argument for parameter 'z' in call}} {{33-33=, z: <#() -> Int#>}}
4448

4549
func trailingClosureMulti2(x: Int, y: () -> Int, z: Int) {} // expected-note * {{here}}
46-
trailingClosureMulti2 { 1 } // expected-error {{trailing closure passed to parameter of type 'Int' that does not accept a closure}}
47-
trailingClosureMulti2() { 1 } // expected-error {{trailing closure passed to parameter of type 'Int' that does not accept a closure}}
48-
trailingClosureMulti2(x: 1) { 1 } // expected-error {{trailing closure passed to parameter of type 'Int' that does not accept a closure}}
50+
trailingClosureMulti2 { 1 }
51+
// expected-error@-1 {{missing arguments for parameters 'x', 'y' in call}}
52+
// expected-error@-2 {{trailing closure passed to parameter of type 'Int' that does not accept a closure}}
53+
trailingClosureMulti2() { 1 }
54+
// expected-error@-1 {{missing arguments for parameters 'x', 'y' in call}}
55+
// expected-error@-2 {{trailing closure passed to parameter of type 'Int' that does not accept a closure}}
56+
trailingClosureMulti2(x: 1) { 1 }
57+
// expected-error@-1 {{missing argument for parameter 'y' in call}} {{27-27=, y: <#() -> Int#>}}
58+
// expected-error@-2 {{trailing closure passed to parameter of type 'Int' that does not accept a closure}}
4959

5060
func param2Func(x: Int, y: Int) {} // expected-note * {{here}}
5161
param2Func(x: 1) // expected-error {{missing argument for parameter 'y' in call}} {{16-16=, y: <#Int#>}}

test/Constraints/diagnostics.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -700,11 +700,10 @@ let a = safeAssign // expected-error {{generic parameter 'T' could not be inferr
700700

701701
// <rdar://problem/21692808> QoI: Incorrect 'add ()' fixit with trailing closure
702702
struct Radar21692808<Element> {
703-
init(count: Int, value: Element) {}
703+
init(count: Int, value: Element) {} // expected-note {{'init(count:value:)' declared here}}
704704
}
705705
func radar21692808() -> Radar21692808<Int> {
706-
return Radar21692808<Int>(count: 1) { // expected-error {{cannot invoke initializer for type 'Radar21692808<Int>' with an argument list of type '(count: Int, @escaping () -> Int)'}}
707-
// expected-note @-1 {{expected an argument list of type '(count: Int, value: Element)'}}
706+
return Radar21692808<Int>(count: 1) { // expected-error {{trailing closure passed to parameter of type 'Int' that does not accept a closure}}
708707
return 1
709708
}
710709
}

0 commit comments

Comments
 (0)