Skip to content

Commit ed046e5

Browse files
authored
Merge pull request #68215 from xedin/rdar-112426330
[CSSimplify] Rework detection of missing/extraneous arguments in closure
2 parents 235764b + 1c8b8d9 commit ed046e5

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
@@ -1227,3 +1227,23 @@ func closureWithCaseArchetype<T>(_: T.Type) {
12271227
}
12281228
}
12291229
}
1230+
1231+
// rdar://112426330 - invalid diagnostic when closure argument is omitted
1232+
do {
1233+
func test<T>(_: T, _: (T) -> Void) {}
1234+
1235+
test(42) { // expected-error {{contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored}} {{13-13= _ in}}
1236+
print("")
1237+
}
1238+
1239+
func context(_: (Int) -> Void) {}
1240+
func context(_: () -> Void) {}
1241+
1242+
context {
1243+
test(42) { // expected-error {{contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored}} {{15-15= _ in}}
1244+
print("")
1245+
}
1246+
}
1247+
1248+
1249+
}

0 commit comments

Comments
 (0)