From 8e2f1c55a8d9e38956011f25f0f22b3b9b1a2857 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Tue, 17 May 2022 16:47:50 -0700 Subject: [PATCH] [CSSimplify] Disfavor choices that have injected `callAsFunction` Ambiguities like: ``` struct S { init(v: Int) {} init(v: Int, _: () -> Void) {} func callAsFunction(_: () -> Void) {} } S(v: 42) { } ``` Should always be resolved in favor of choice that doesn't require injection of `.callAsFunction`, so let's try to avoid solving if such an overload has already been found. (cherry picked from commit 7898b5a0883f66efdcd6b14d66d8bca09e742d4e) --- lib/Sema/CSSimplify.cpp | 1 + .../result_builder_callAsFunction.swift | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 test/Constraints/result_builder_callAsFunction.swift diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index b70c5ba62506d..b1ac671ff1fdd 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -11402,6 +11402,7 @@ ConstraintSystem::simplifyApplicableFnConstraint( FunctionType::get(trailingClosureTypes, callAsFunctionResultTy, FunctionType::ExtInfo()); + increaseScore(SK_DisfavoredOverload); // Form an unsolved constraint to apply trailing closures to a // callable type produced by `.init`. This constraint would become // active when `callableType` is bound. diff --git a/test/Constraints/result_builder_callAsFunction.swift b/test/Constraints/result_builder_callAsFunction.swift new file mode 100644 index 0000000000000..a1546345b94d9 --- /dev/null +++ b/test/Constraints/result_builder_callAsFunction.swift @@ -0,0 +1,36 @@ +// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macosx10.15 -swift-version 5 -debug-constraints > %t.log 2>&1 +// RUN: %FileCheck %s < %t.log + +// REQUIRES: objc_interop +// REQUIRES: OS=macosx + +protocol View {} +protocol Callable {} + +struct EmptyView : View {} + +@resultBuilder struct ViewBuilder { + static func buildBlock(_ content: Content) -> Content where Content : View { fatalError() } +} + +extension Callable { + func callAsFunction(@ViewBuilder _: () -> T) -> some View { EmptyView() } +} + +struct MyView : View { + init(v: Int, @ViewBuilder _: () -> Content) {} +} + +extension MyView : Callable where Content == EmptyView { + init(v: Int) {} +} + +// CHECK: (overload set choice binding $T6 := (Int) -> MyView<{{.*}}>) +// CHECK-NEXT: (increasing score due to disfavored overload) +// CHECK-NEXT: (solution is worse than the best solution) + +func test() -> some View { + return MyView(v: 42) { + return EmptyView() + } +}