Skip to content

Commit 4b2b436

Browse files
authored
Merge pull request #29845 from omochi/trailing-closure-position
[ConstraintSystem] Accept trailing closure if multiple defaulted parameters after last function parameter
2 parents a0d3542 + 252e82f commit 4b2b436

File tree

2 files changed

+18
-10
lines changed

2 files changed

+18
-10
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -430,24 +430,24 @@ matchCallArguments(SmallVectorImpl<AnyFunctionType::Param> &args,
430430

431431
// If we have a trailing closure, it maps to the last parameter.
432432
if (hasTrailingClosure && numParams > 0) {
433-
unsigned lastParamIdx = numParams - 1;
434-
bool lastAcceptsTrailingClosure =
435-
acceptsTrailingClosure(params[lastParamIdx]);
436-
437433
// If the last parameter is defaulted, this might be
438434
// an attempt to use a trailing closure with previous
439435
// parameter that accepts a function type e.g.
440436
//
441437
// func foo(_: () -> Int, _ x: Int = 0) {}
442438
// foo { 42 }
443-
if (!lastAcceptsTrailingClosure && numParams > 1 &&
444-
paramInfo.hasDefaultArgument(lastParamIdx)) {
445-
auto paramType = params[lastParamIdx - 1].getPlainType();
446-
// If the parameter before defaulted last accepts.
447-
if (paramType->is<AnyFunctionType>()) {
439+
bool lastAcceptsTrailingClosure = false;
440+
unsigned lastParamIdx = numParams - 1;
441+
for (unsigned i : indices(params)) {
442+
unsigned idx = numParams - 1 - i;
443+
if (acceptsTrailingClosure(params[idx])) {
448444
lastAcceptsTrailingClosure = true;
449-
lastParamIdx -= 1;
445+
lastParamIdx = idx;
446+
break;
450447
}
448+
if (paramInfo.hasDefaultArgument(idx))
449+
continue;
450+
break;
451451
}
452452

453453
bool isExtraClosure = false;

test/Constraints/closures.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,14 @@ func test_trailing_closure_with_defaulted_last() {
921921
func foo<T>(fn: () -> T, value: Int = 0) {}
922922
foo { 42 } // Ok
923923
foo(fn: { 42 }) // Ok
924+
925+
func bar<T>(type: T.Type, fn: T, a: Int = 0) {}
926+
bar(type: (() -> Int).self) { 42 }
927+
bar(type: (() -> Int).self, fn: { 42 })
928+
929+
func baz(fn: () -> Int, a: Int = 0, b: Int = 0, c: Int = 0) {}
930+
baz { 42 }
931+
baz(fn: { 42 })
924932
}
925933

926934
// Test that even in multi-statement closure case we still pick up `(Action) -> Void` over `Optional<(Action) -> Void>`.

0 commit comments

Comments
 (0)