Skip to content

Commit c5ae6c9

Browse files
committed
[ConstraintSystem] Detect missing/extraneous arguments even if there is optional injection required
If parameter type is optional let's ignore that since argument could be either optional itself or be injected into optional implicitly. ```swift func foo(_: ((Int, Int) -> Void)!) {} foo { _ in } // Missing second closure parameter ```
1 parent 506cd7d commit c5ae6c9

File tree

3 files changed

+23
-5
lines changed

3 files changed

+23
-5
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4100,7 +4100,12 @@ bool MissingArgumentsFailure::diagnoseClosure(ClosureExpr *closure) {
41004100
if (locator->isForContextualType()) {
41014101
funcType = cs.getContextualType(locator->getAnchor())->getAs<FunctionType>();
41024102
} else if (auto info = cs.getFunctionArgApplyInfo(locator)) {
4103-
funcType = info->getParamType()->getAs<FunctionType>();
4103+
auto paramType = info->getParamType();
4104+
// Drop a single layer of optionality because argument could get injected
4105+
// into optional and that doesn't contribute to the problem.
4106+
if (auto objectType = paramType->getOptionalObjectType())
4107+
paramType = objectType;
4108+
funcType = paramType->getAs<FunctionType>();
41044109
} else if (locator->isLastElement<LocatorPathElt::ClosureResult>()) {
41054110
// Based on the locator we know this this is something like this:
41064111
// `let _: () -> ((Int) -> Void) = { return {} }`.

lib/Sema/CSSimplify.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1692,20 +1692,33 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
16921692
if (!shouldAttemptFixes())
16931693
return getTypeMatchFailure(argumentLocator);
16941694

1695-
auto *anchor = locator.trySimplifyToExpr();
1695+
auto *loc = getConstraintLocator(locator);
1696+
1697+
// If this is conversion between optional (or IUO) parameter
1698+
// and argument, let's drop the last path element so locator
1699+
// could be simplified down to an argument expression.
1700+
//
1701+
// func foo(_: ((Int, Int) -> Void)?) {}
1702+
// _ = foo { _ in } <- missing second closure parameter.
1703+
if (loc->isLastElement<LocatorPathElt::OptionalPayload>()) {
1704+
auto path = loc->getPath();
1705+
loc = getConstraintLocator(loc->getAnchor(), path.drop_back());
1706+
}
1707+
1708+
auto *anchor = simplifyLocatorToAnchor(loc);
16961709
if (!anchor)
16971710
return getTypeMatchFailure(argumentLocator);
16981711

16991712
// If there are missing arguments, let's add them
17001713
// using parameter as a template.
17011714
if (diff < 0) {
17021715
if (fixMissingArguments(*this, anchor, func1Params, func2Params,
1703-
abs(diff), locator))
1716+
abs(diff), loc))
17041717
return getTypeMatchFailure(argumentLocator);
17051718
} else {
17061719
// If there are extraneous arguments, let's remove
17071720
// them from the list.
1708-
if (fixExtraneousArguments(*this, func2, func1Params, diff, locator))
1721+
if (fixExtraneousArguments(*this, func2, func1Params, diff, loc))
17091722
return getTypeMatchFailure(argumentLocator);
17101723

17111724
// Drop all of the extraneous arguments.

test/Constraints/tuple_arguments.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1526,7 +1526,7 @@ func r32214649_3<X>(_ a: [X]) -> [X] {
15261526

15271527
func rdar32301091_1(_ :((Int, Int) -> ())!) {}
15281528
rdar32301091_1 { _ in }
1529-
// expected-error@-1 {{cannot convert value of type '(_) -> ()' to expected argument type '((Int, Int) -> ())?'}}
1529+
// expected-error@-1 {{contextual closure type '(Int, Int) -> ()' expects 2 arguments, but 1 was used in closure body}} {{19-19=,_ }}
15301530

15311531
func rdar32301091_2(_ :(Int, Int) -> ()) {}
15321532
rdar32301091_2 { _ in }

0 commit comments

Comments
 (0)