Skip to content

Commit 1c8b8d9

Browse files
committed
[CSSimplify] Rework detection of missing/extraneous arguments in closure
Checking type variables is no longer necessary because constraint system now stores types of all closures it encountered, this makes detection logic more reliable as well. Resolves: rdar://112426330
1 parent 1305901 commit 1c8b8d9

File tree

2 files changed

+52
-37
lines changed

2 files changed

+52
-37
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 32 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5808,9 +5808,6 @@ bool ConstraintSystem::repairFailures(
58085808
}
58095809

58105810
case ConstraintLocator::FunctionArgument: {
5811-
auto *argLoc = getConstraintLocator(
5812-
locator.withPathElement(LocatorPathElt::SynthesizedArgument(0)));
5813-
58145811
// Let's drop the last element which points to a single argument
58155812
// and see if this is a contextual mismatch.
58165813
path.pop_back();
@@ -5819,38 +5816,41 @@ bool ConstraintSystem::repairFailures(
58195816
path.back().getKind() == ConstraintLocator::ContextualType))
58205817
return false;
58215818

5822-
auto arg = llvm::find_if(getTypeVariables(),
5823-
[&argLoc](const TypeVariableType *typeVar) {
5824-
return typeVar->getImpl().getLocator() == argLoc;
5825-
});
5819+
if (auto argToParamElt =
5820+
path.back().getAs<LocatorPathElt::ApplyArgToParam>()) {
5821+
auto loc = getConstraintLocator(anchor, path);
58265822

5827-
// What we have here is a form or tuple splat with no arguments
5828-
// demonstrated by following example:
5829-
//
5830-
// func foo<T: P>(_: T, _: (T.Element) -> Int) {}
5831-
// foo { 42 }
5832-
//
5833-
// In cases like this `T.Element` might be resolved to `Void`
5834-
// which means that we have to try a single empty tuple argument
5835-
// as a narrow exception to SE-0110, see `matchFunctionTypes`.
5836-
//
5837-
// But if `T.Element` didn't get resolved to `Void` we'd like
5838-
// to diagnose this as a missing argument which can't be ignored or
5839-
// a tuple is trying to be inferred as a tuple for destructuring but
5840-
// contextual argument does not match(in this case we remove the extra
5841-
// closure arguments).
5842-
if (arg != getTypeVariables().end()) {
5843-
if (auto argToParamElt =
5844-
path.back().getAs<LocatorPathElt::ApplyArgToParam>()) {
5845-
auto loc = getConstraintLocator(anchor, path);
5846-
auto closureAnchor =
5847-
getAsExpr<ClosureExpr>(simplifyLocatorToAnchor(loc));
5848-
if (rhs->is<TupleType>() && closureAnchor &&
5849-
closureAnchor->getParameters()->size() > 1) {
5823+
if (auto closure = getAsExpr<ClosureExpr>(simplifyLocatorToAnchor(loc))) {
5824+
auto closureTy = getClosureType(closure);
5825+
// What we have here is a form or tuple splat with no arguments
5826+
// demonstrated by following example:
5827+
//
5828+
// func foo<T: P>(_: T, _: (T.Element) -> Int) {}
5829+
// foo { 42 }
5830+
//
5831+
// In cases like this `T.Element` might be resolved to `Void`
5832+
// which means that we have to try a single empty tuple argument
5833+
// as a narrow exception to SE-0110, see `matchFunctionTypes`.
5834+
//
5835+
// But if `T.Element` didn't get resolved to `Void` we'd like
5836+
// to diagnose this as a missing argument which can't be ignored or
5837+
// a tuple is trying to be inferred as a tuple for destructuring but
5838+
// contextual argument does not match(in this case we remove the extra
5839+
// closure arguments).
5840+
if (closureTy->getNumParams() == 0) {
5841+
conversionsOrFixes.push_back(AddMissingArguments::create(
5842+
*this, {SynthesizedArg{0, AnyFunctionType::Param(lhs)}}, loc));
5843+
break;
5844+
}
5845+
5846+
// Since this is a problem with `FunctionArgument` we know that the
5847+
// contextual type only has one parameter, if closure has more than
5848+
// that the fix is to remove extraneous ones.
5849+
if (closureTy->getNumParams() > 1) {
58505850
auto callee = getCalleeLocator(loc);
58515851
if (auto overload = findSelectedOverloadFor(callee)) {
5852-
auto fnType =
5853-
simplifyType(overload->adjustedOpenedType)->castTo<FunctionType>();
5852+
auto fnType = simplifyType(overload->adjustedOpenedType)
5853+
->castTo<FunctionType>();
58545854
auto paramIdx = argToParamElt->getParamIdx();
58555855
auto paramType = fnType->getParams()[paramIdx].getParameterType();
58565856
if (auto paramFnType = paramType->getAs<FunctionType>()) {
@@ -5861,11 +5861,6 @@ bool ConstraintSystem::repairFailures(
58615861
}
58625862
}
58635863
}
5864-
5865-
conversionsOrFixes.push_back(AddMissingArguments::create(
5866-
*this, {SynthesizedArg{0, AnyFunctionType::Param(*arg)}},
5867-
getConstraintLocator(anchor, path)));
5868-
break;
58695864
}
58705865

58715866
auto *parentLoc = getConstraintLocator(anchor, path);

test/Constraints/closures.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,3 +1229,23 @@ func closureWithCaseArchetype<T>(_: T.Type) {
12291229
}
12301230
}
12311231
}
1232+
1233+
// rdar://112426330 - invalid diagnostic when closure argument is omitted
1234+
do {
1235+
func test<T>(_: T, _: (T) -> Void) {}
1236+
1237+
test(42) { // expected-error {{contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored}} {{13-13= _ in}}
1238+
print("")
1239+
}
1240+
1241+
func context(_: (Int) -> Void) {}
1242+
func context(_: () -> Void) {}
1243+
1244+
context {
1245+
test(42) { // expected-error {{contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored}} {{15-15= _ in}}
1246+
print("")
1247+
}
1248+
}
1249+
1250+
1251+
}

0 commit comments

Comments
 (0)