Skip to content

Commit c968c14

Browse files
committed
[Diagnostics] Cover single explicit tuple argument -> N parameters via missing arguments fix
Expand tuple into N arguments to cover expect parameters. This covers cases like this: ```swift func foo(_: (Int, Int) -> Void) {} foo { (bar: (Int, Int)) in } // used a single tuple type `(Int, Int)` // instead of two distinct arguments ```
1 parent 2f325fa commit c968c14

File tree

2 files changed

+21
-13
lines changed

2 files changed

+21
-13
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4091,10 +4091,8 @@ bool FailureDiagnosis::diagnoseClosureExpr(
40914091
return true;
40924092
}
40934093

4094-
MissingArgumentsFailure failure(
4095-
expr, CS, inferredArgCount - actualArgCount,
4096-
CS.getConstraintLocator(CE, LocatorPathElt::ContextualType()));
4097-
return failure.diagnoseAsError();
4094+
// Missing arguments are already diagnosed via new diagnostic framework.
4095+
return false;
40984096
}
40994097

41004098
// Coerce parameter types here only if there are no unresolved

lib/Sema/CSSimplify.cpp

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,16 +1179,26 @@ static bool fixMissingArguments(ConstraintSystem &cs, Expr *anchor,
11791179
// tuple e.g. `$0.0`.
11801180
Optional<TypeBase *> argumentTuple;
11811181
if (isa<ClosureExpr>(anchor) && isSingleTupleParam(ctx, args)) {
1182-
auto isParam = [](const Expr *expr) {
1183-
if (auto *DRE = dyn_cast<DeclRefExpr>(expr)) {
1184-
if (auto *decl = DRE->getDecl())
1185-
return isa<ParamDecl>(decl);
1182+
auto argType = args.back().getPlainType();
1183+
// Let's unpack argument tuple into N arguments, this corresponds
1184+
// to something like `foo { (bar: (Int, Int)) in }` where `foo`
1185+
// has a single parameter of type `(Int, Int) -> Void`.
1186+
if (auto *tuple = argType->getAs<TupleType>()) {
1187+
args.pop_back();
1188+
for (const auto &elt : tuple->getElements()) {
1189+
args.push_back(AnyFunctionType::Param(elt.getType(), elt.getName(),
1190+
elt.getParameterFlags()));
11861191
}
1187-
return false;
1188-
};
1192+
} else if (auto *typeVar = argType->getAs<TypeVariableType>()) {
1193+
auto isParam = [](const Expr *expr) {
1194+
if (auto *DRE = dyn_cast<DeclRefExpr>(expr)) {
1195+
if (auto *decl = DRE->getDecl())
1196+
return isa<ParamDecl>(decl);
1197+
}
1198+
return false;
1199+
};
11891200

1190-
const auto &arg = args.back();
1191-
if (auto *argTy = arg.getPlainType()->getAs<TypeVariableType>()) {
1201+
// Something like `foo { x in }` or `foo { $0 }`
11921202
anchor->forEachChildExpr([&](Expr *expr) -> Expr * {
11931203
if (auto *UDE = dyn_cast<UnresolvedDotExpr>(expr)) {
11941204
if (!isParam(UDE->getBase()))
@@ -1200,7 +1210,7 @@ static bool fixMissingArguments(ConstraintSystem &cs, Expr *anchor,
12001210
llvm::any_of(params, [&](const AnyFunctionType::Param &param) {
12011211
return param.getLabel() == name;
12021212
})) {
1203-
argumentTuple.emplace(argTy);
1213+
argumentTuple.emplace(typeVar);
12041214
args.pop_back();
12051215
return nullptr;
12061216
}

0 commit comments

Comments
 (0)