Skip to content

Commit 5b71a7d

Browse files
Merge pull request #82156 from AnthonyLatsis/camellia-sinensis-6.2
[6.2] Sema: Never record argument label mismatches for unlabeled trailing closures
2 parents 4b3943a + da1922f commit 5b71a7d

File tree

3 files changed

+46
-1
lines changed

3 files changed

+46
-1
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,13 @@ static bool matchCallArgumentsImpl(
377377
assert(argIdx != numArgs && "Must have a valid index to claim");
378378
assert(!claimedArgs[argIdx] && "Argument already claimed");
379379

380+
// Prevent recording of an argument label mismatche for an unlabeled
381+
// trailing closure. An unlabeled trailing closure is necessarily the first
382+
// one and vice versa, per language syntax.
383+
if (unlabeledTrailingClosureArgIndex == argIdx) {
384+
expectedName = Identifier();
385+
}
386+
380387
if (!actualArgNames.empty()) {
381388
// We're recording argument names; record this one.
382389
actualArgNames[argIdx] = expectedName;

lib/Sema/MiscDiagnostics.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2697,8 +2697,10 @@ bool swift::diagnoseArgumentLabelError(ASTContext &ctx,
26972697
}
26982698
}
26992699

2700+
assert((numMissing + numExtra + numWrong > 0) &&
2701+
"Should not call this function with nothing to diagnose");
2702+
27002703
// Emit the diagnostic.
2701-
assert(numMissing > 0 || numExtra > 0 || numWrong > 0);
27022704
llvm::SmallString<16> haveBuffer; // note: diagOpt has references to this
27032705
llvm::SmallString<16> expectedBuffer; // note: diagOpt has references to this
27042706

test/expr/closure/trailing.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,3 +488,39 @@ func rdar92521618() {
488488
if let _ = { foo {} }() {}
489489
guard let _ = { foo {} }() else { return }
490490
}
491+
492+
// Argument matching never binds trailing closure arguments to
493+
// defaulted/variadic parameters of non-function type.
494+
do {
495+
// Trailing closure not considered fulfilled by 'arg'.
496+
// Note: Used to crash.
497+
do {
498+
func variadic(arg: Int...) {} // expected-note@:10 {{'variadic(arg:)' declared here}}{{none}}
499+
func defaulted(arg: Int = 0) {}
500+
501+
let _ = variadic { return () }
502+
// expected-error@-1:22 {{trailing closure passed to parameter of type 'Int' that does not accept a closure}}{{none}}
503+
let _ = defaulted { return () }
504+
// expected-error@-1:23 {{extra trailing closure passed in call}}{{none}}
505+
}
506+
// Trailing closure considered fulfilled by 'x' instead of 'arg'.
507+
do {
508+
func variadic(arg: Int..., x: String) {} // expected-note@:10 {{'variadic(arg:x:)' declared here}}{{none}}
509+
func defaulted(arg: Int = 0, x: String) {} // expected-note@:10 {{'defaulted(arg:x:)' declared here}}{{none}}
510+
511+
let _ = variadic { return () }
512+
// expected-error@-1:22 {{trailing closure passed to parameter of type 'String' that does not accept a closure}}{{none}}
513+
let _ = defaulted { return () }
514+
// expected-error@-1:23 {{trailing closure passed to parameter of type 'String' that does not accept a closure}}{{none}}
515+
}
516+
// Trailing closure considered fulfilled by 'arg'; has function type.
517+
do {
518+
func variadic(arg: ((Int) -> Void)...) {}
519+
func defaulted(arg: ((Int) -> Void) = { _ in }) {}
520+
521+
let _ = variadic { return () }
522+
// expected-error@-1:22 {{contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored}}{{23-23= _ in}}
523+
let _ = defaulted { return () }
524+
// expected-error@-1:23 {{contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored}}{{24-24= _ in}}
525+
}
526+
}

0 commit comments

Comments
 (0)