Skip to content

Commit 0300139

Browse files
[Sema][Diagnostics] Improving diagnostics for function type coerce failure
1 parent 0988236 commit 0300139

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2761,6 +2761,17 @@ bool ContextualFailure::diagnoseAsNote() {
27612761
}
27622762
}
27632763

2764+
// Note that mentions candidate type number of parameters diff.
2765+
auto fromFnType = getFromType()->getAs<FunctionType>();
2766+
auto toFnType = getToType()->getAs<FunctionType>();
2767+
if (fromFnType && toFnType &&
2768+
fromFnType->getNumParams() > toFnType->getNumParams()) {
2769+
emitDiagnosticAt(decl, diag::candidate_with_extraneous_args, fromFnType,
2770+
fromFnType->getNumParams(), toFnType,
2771+
toFnType->getNumParams());
2772+
return true;
2773+
}
2774+
27642775
emitDiagnosticAt(decl, diag::found_candidate_type, getFromType());
27652776
return true;
27662777
}

lib/Sema/CSSimplify.cpp

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3425,18 +3425,36 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
34253425
if (!anchor)
34263426
return getTypeMatchFailure(argumentLocator);
34273427

3428-
// If there are missing arguments, let's add them
3429-
// using parameter as a template.
3430-
if (diff < 0) {
3431-
if (fixMissingArguments(*this, anchor, func1Params, func2Params,
3432-
abs(diff), loc))
3428+
// The param diff is in a function type coercion context
3429+
//
3430+
// func fn(_: Int) {}
3431+
// let i: Int = 0
3432+
// (fn as (Int, Int) -> Void)(i, i)
3433+
//
3434+
// Since we are not in a function argument application, so simply record
3435+
// a function type mismatch instead of an argument fix.
3436+
// Except for when a closure is a subexpr because missing and extraneous
3437+
// arg fix can properly handle closure diagnostic.
3438+
if (loc->isForCoercion() && !isExpr<ClosureExpr>(anchor)) {
3439+
auto *fix = ContextualMismatch::create(*this, func1, func2, loc);
3440+
if (recordFix(fix))
34333441
return getTypeMatchFailure(argumentLocator);
34343442
} else {
3435-
// If there are extraneous arguments, let's remove
3436-
// them from the list.
3437-
if (fixExtraneousArguments(*this, func2, func1Params, diff, loc))
3438-
return getTypeMatchFailure(argumentLocator);
3443+
// If there are missing arguments, let's add them
3444+
// using parameter as a template.
3445+
if (diff < 0) {
3446+
if (fixMissingArguments(*this, anchor, func1Params, func2Params,
3447+
abs(diff), loc))
3448+
return getTypeMatchFailure(argumentLocator);
3449+
} else {
3450+
// If there are extraneous arguments, let's remove
3451+
// them from the list.
3452+
if (fixExtraneousArguments(*this, func2, func1Params, diff, loc))
3453+
return getTypeMatchFailure(argumentLocator);
3454+
}
3455+
}
34393456

3457+
if (diff > 0) {
34403458
// Drop all of the extraneous arguments.
34413459
auto numParams = func2Params.size();
34423460
func1Params.erase(func1Params.begin() + numParams, func1Params.end());

0 commit comments

Comments
 (0)