Skip to content

Commit c664ac0

Browse files
committed
[CSSimplify] While attempting to synthesize missing arguments account for "implode" case
In situations like this: ```swift func foo(_: (Int, Int) -> Void) {} foo { $0.0 + $0.1 } ``` Parameters are expected to be a single tuple by mistake, to account for that solver can generate N new arguments and bind a single existing argument to tuple formed from them.
1 parent 1c54c5a commit c664ac0

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,6 +1262,43 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
12621262
// If there are missing arguments, let's add them
12631263
// using parameter as a template.
12641264
if (diff < 0) {
1265+
// If there are N parameters but a single closure argument
1266+
// (which might be anonymous), it's most likely used as a
1267+
// tuple e.g. `$0.0`.
1268+
Optional<TypeBase *> argumentTuple;
1269+
if (isa<ClosureExpr>(anchor) && isSingleParam(func1Params)) {
1270+
auto isParam = [](const Expr *expr) {
1271+
if (auto *DRE = dyn_cast<DeclRefExpr>(expr)) {
1272+
if (auto *decl = DRE->getDecl())
1273+
return isa<ParamDecl>(decl);
1274+
}
1275+
return false;
1276+
};
1277+
1278+
const auto &arg = func1Params.back();
1279+
if (auto *argTy = arg.getPlainType()->getAs<TypeVariableType>()) {
1280+
anchor->forEachChildExpr([&](Expr *expr) -> Expr * {
1281+
if (auto *UDE = dyn_cast<UnresolvedDotExpr>(expr)) {
1282+
if (!isParam(UDE->getBase()))
1283+
return expr;
1284+
1285+
auto name = UDE->getName().getBaseIdentifier();
1286+
unsigned index = 0;
1287+
if (!name.str().getAsInteger(10, index) ||
1288+
llvm::any_of(func2Params,
1289+
[&](const AnyFunctionType::Param &param) {
1290+
return param.getLabel() == name;
1291+
})) {
1292+
argumentTuple.emplace(argTy);
1293+
func1Params.pop_back();
1294+
return nullptr;
1295+
}
1296+
}
1297+
return expr;
1298+
});
1299+
}
1300+
}
1301+
12651302
for (unsigned i = func1Params.size(),
12661303
n = func2Params.size(); i != n; ++i) {
12671304
auto *argLoc = getConstraintLocator(
@@ -1278,6 +1315,15 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
12781315

12791316
if (recordFix(fix))
12801317
return getTypeMatchFailure(argumentLocator);
1318+
1319+
// If the argument was a single "tuple", let's bind newly
1320+
// synthesized arguments to it.
1321+
if (argumentTuple) {
1322+
addConstraint(ConstraintKind::Bind, *argumentTuple,
1323+
FunctionType::composeInput(getASTContext(), func1Params,
1324+
/*canonicalVararg=*/false),
1325+
getConstraintLocator(anchor));
1326+
}
12811327
} else {
12821328
// TODO(diagnostics): Add handling of extraneous arguments.
12831329
return getTypeMatchFailure(argumentLocator);

0 commit comments

Comments
 (0)