Skip to content

Commit 9588d51

Browse files
committed
[CSOptimizer] Fix a conditional that ignores function type parameters to look through optionals
Since parameters that have function types don't participate in ranking, function types that are wrapped in optionals should be excluded as well, because it's possible to overload on that and such overloads with optional types would gain an undue advantage. For example: ``` func test(_: (() -> Void)?) {} func test(_: () -> Void) {} func compute(handler: () -> Void) { test(handler) } ``` Without this change the second overload would be ignored and the first one would be an exact match. Resolves: rdar://157234317
1 parent e2ad4a9 commit 9588d51

File tree

2 files changed

+9
-1
lines changed

2 files changed

+9
-1
lines changed

lib/Sema/CSOptimizer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1598,7 +1598,7 @@ static void determineBestChoicesInContext(
15981598
// FIXME: Let's skip matching function types for now
15991599
// because they have special rules for e.g. Concurrency
16001600
// (around @Sendable) and @convention(c).
1601-
if (paramType->is<FunctionType>())
1601+
if (paramType->lookThroughAllOptionalTypes()->is<FunctionType>())
16021602
continue;
16031603

16041604
// The idea here is to match the parameter type against

test/SILOptimizer/infinite_recursion.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,3 +352,11 @@ func recursionMatchingTypeArgs2<T: P, V: P>(_ t: T.Type, _ v: V.Type) {
352352
recursionMatchingTypeArgs2(T.self, V.self) // expected-warning {{function call causes an infinite recursion}}
353353
}
354354

355+
func testNoInfiniteRecursionWithOverloadingOnOptional() {
356+
func test(handler: @escaping (Bool) -> Void) {
357+
}
358+
359+
func test(handler: ((Bool) -> Void)?) {
360+
test(handler: handler ?? { _ in }) // Ok
361+
}
362+
}

0 commit comments

Comments
 (0)