Skip to content

Commit 84a2c5c

Browse files
committed
[Sema] Improve extra trailing closure diagnostic
Emit the specialized extraneous trailing closure diagnostic for multiple trailing closures and unlabelled unary argument lists, and add a specialized trailing closure version for the multiple extraneous case.
1 parent 5aeb49f commit 84a2c5c

File tree

4 files changed

+38
-5
lines changed

4 files changed

+38
-5
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1267,7 +1267,8 @@ ERROR(extra_argument_named,none,
12671267
ERROR(extra_argument_positional,none,
12681268
"extra argument in call", ())
12691269
ERROR(extra_arguments_in_call,none,
1270-
"extra arguments at positions %0 in call", (StringRef))
1270+
"extra %select{arguments|trailing closures}0 at positions %1 in call",
1271+
(bool, StringRef))
12711272
ERROR(extra_argument_to_nullary_call,none,
12721273
"argument passed to call that takes no arguments", ())
12731274
ERROR(extra_trailing_closure_in_call,none,

lib/Sema/CSDiagnostics.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5197,7 +5197,16 @@ bool ExtraneousArgumentsFailure::diagnoseAsError() {
51975197
},
51985198
[&] { OS << ", "; });
51995199

5200-
emitDiagnostic(diag::extra_arguments_in_call, OS.str());
5200+
bool areTrailingClosures = false;
5201+
if (auto *argExpr = getArgumentListExprFor(getLocator())) {
5202+
if (auto i = argExpr->getUnlabeledTrailingClosureIndexOfPackedArgument()) {
5203+
areTrailingClosures = llvm::all_of(ExtraArgs, [&](auto &pair) {
5204+
return pair.first >= i;
5205+
});
5206+
}
5207+
}
5208+
5209+
emitDiagnostic(diag::extra_arguments_in_call, areTrailingClosures, OS.str());
52015210

52025211
if (auto overload = getCalleeOverloadChoiceIfAvailable(getLocator())) {
52035212
if (auto *decl = overload->choice.getDeclOrNull()) {
@@ -5248,9 +5257,12 @@ bool ExtraneousArgumentsFailure::diagnoseSingleExtraArgument() const {
52485257
auto argExpr = tuple ? tuple->getElement(index)
52495258
: cast<ParenExpr>(arguments)->getSubExpr();
52505259

5260+
auto trailingClosureIdx =
5261+
arguments->getUnlabeledTrailingClosureIndexOfPackedArgument();
5262+
auto isTrailingClosure = trailingClosureIdx && index >= *trailingClosureIdx;
5263+
52515264
auto loc = argExpr->getLoc();
5252-
if (tuple && index == tuple->getNumElements() - 1 &&
5253-
tuple->hasTrailingClosure()) {
5265+
if (isTrailingClosure) {
52545266
emitDiagnosticAt(loc, diag::extra_trailing_closure_in_call)
52555267
.highlight(argExpr->getSourceRange());
52565268
} else if (ContextualType->getNumParams() == 0) {

test/Constraints/argument_matching.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,3 +1762,23 @@ func rdar70764991() {
17621762
bar(str, S.foo) // expected-error {{unnamed argument #1 must precede unnamed argument #2}} {{9-12=}} {{14-14=str}}
17631763
}
17641764
}
1765+
1766+
func testExtraTrailingClosure() {
1767+
func foo() {}
1768+
foo() {} // expected-error@:9 {{extra trailing closure passed in call}}
1769+
foo {} // expected-error@:7 {{extra trailing closure passed in call}}
1770+
foo {} x: {} // expected-error@:7 {{argument passed to call that takes no arguments}}
1771+
1772+
func bar(_ x: Int) {} // expected-note 2{{'bar' declared here}}
1773+
bar(5) {} // expected-error@:10 {{extra trailing closure passed in call}}
1774+
bar(0) {} x: {} // expected-error@:6 {{extra trailing closures at positions #2, #3 in call}}
1775+
bar(5, "") {} // expected-error@:6 {{extra arguments at positions #2, #3 in call}}
1776+
1777+
func baz(_ fn: () -> Void) {} // expected-note {{'baz' declared here}}
1778+
baz {} x: {} // expected-error@:13 {{extra trailing closure passed in call}}
1779+
baz({}) {} // expected-error@:11 {{extra trailing closure passed in call}}
1780+
baz({}) {} y: {} // expected-error@:6 {{extra trailing closures at positions #2, #3 in call}}
1781+
1782+
func qux(x: () -> Void, y: () -> Void, z: () -> Void) {} // expected-note {{'qux(x:y:z:)' declared here}}
1783+
qux() {} m: {} y: {} n: {} z: {} o: {} // expected-error@:6 {{extra trailing closures at positions #2, #4, #6 in call}}
1784+
}

test/Parse/trailing_closures.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func f() -> Int { 42 }
116116
// This should be interpreted as a trailing closure, instead of being
117117
// interpreted as a computed property with undesired initial value.
118118
struct TrickyTest {
119-
var x : Int = f () { // expected-error {{argument passed to call that takes no arguments}}
119+
var x : Int = f () { // expected-error {{extra trailing closure passed in call}}
120120
3
121121
}
122122
}

0 commit comments

Comments
 (0)