Skip to content

Commit 8ac1f34

Browse files
authored
Merge pull request #22098 from DaveAMoore/SR-9738
2 parents 19e199e + 6a0d540 commit 8ac1f34

File tree

2 files changed

+20
-8
lines changed

2 files changed

+20
-8
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2612,7 +2612,6 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
26122612
// non-function/non-metatype type, then we cannot call it!
26132613
if (!isUnresolvedOrTypeVarType(fnType) &&
26142614
!fnType->is<AnyFunctionType>() && !fnType->is<MetatypeType>()) {
2615-
26162615
auto arg = callExpr->getArg();
26172616
auto isDynamicCallable =
26182617
CS.DynamicCallableCache[fnType->getCanonicalType()].isValid();
@@ -2625,7 +2624,7 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
26252624
return funcDecl && funcDecl->isCallAsFunctionMethod();
26262625
});
26272626

2628-
// Diagnose @dynamicCallable errors.
2627+
// Diagnose specific @dynamicCallable errors.
26292628
if (isDynamicCallable) {
26302629
auto dynamicCallableMethods =
26312630
CS.DynamicCallableCache[fnType->getCanonicalType()];
@@ -2644,13 +2643,12 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
26442643
}
26452644
}
26462645

2647-
if (fnType->is<ExistentialMetatypeType>()) {
2646+
auto isExistentialMetatypeType = fnType->is<ExistentialMetatypeType>();
2647+
if (isExistentialMetatypeType) {
26482648
auto diag = diagnose(arg->getStartLoc(),
26492649
diag::missing_init_on_metatype_initialization);
26502650
diag.highlight(fnExpr->getSourceRange());
2651-
}
2652-
2653-
if (!fnType->is<ExistentialMetatypeType>()) {
2651+
} else if (!isDynamicCallable) {
26542652
auto diag = diagnose(arg->getStartLoc(),
26552653
diag::cannot_call_non_function_value, fnType);
26562654
diag.highlight(fnExpr->getSourceRange());
@@ -2669,7 +2667,7 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
26692667
// the line after the callee, then it's likely the user forgot to
26702668
// write "do" before their brace stmt.
26712669
// Note that line differences of more than 1 are diagnosed during parsing.
2672-
if (auto *PE = dyn_cast<ParenExpr>(arg))
2670+
if (auto *PE = dyn_cast<ParenExpr>(arg)) {
26732671
if (PE->hasTrailingClosure() && isa<ClosureExpr>(PE->getSubExpr())) {
26742672
auto *closure = cast<ClosureExpr>(PE->getSubExpr());
26752673
auto &SM = CS.getASTContext().SourceMgr;
@@ -2681,9 +2679,14 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
26812679
.fixItInsert(closure->getStartLoc(), "do ");
26822680
}
26832681
}
2682+
}
26842683

2685-
if (!isDynamicCallable && !hasCallAsFunctionMethods)
2684+
// Use the existing machinery to provide more useful diagnostics for
2685+
// @dynamicCallable calls, rather than cannot_call_non_function_value.
2686+
if ((isExistentialMetatypeType || !isDynamicCallable) &&
2687+
!hasCallAsFunctionMethods) {
26862688
return true;
2689+
}
26872690
}
26882691

26892692
bool hasTrailingClosure = callArgHasTrailingClosure(callExpr->getArg());

test/attr/attr_dynamic_callable.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ func testCallable(
4949
d(x1: 1, 2.0, x2: 3)
5050
}
5151

52+
func testCallableDiagnostics(
53+
a: Callable, b: DiscardableResult, c: Throwing, d: KeywordArgumentCallable
54+
) {
55+
a("hello", "world") // expected-error {{cannot invoke 'a' with an argument list of type '(String, String)'}}
56+
b("hello", "world") // expected-error {{cannot invoke 'b' with an argument list of type '(String, String)'}}
57+
try? c(1, 2, 3, 4) // expected-error {{cannot invoke 'c' with an argument list of type '(Int, Int, Int, Int)'}}
58+
d(x1: "hello", x2: "world") // expected-error {{cannot invoke 'd' with an argument list of type '(x1: String, x2: String)'}}
59+
}
60+
5261
func testIUO(
5362
a: Callable!, b: DiscardableResult!, c: Throwing!, d: KeywordArgumentCallable!
5463
) {

0 commit comments

Comments
 (0)