Skip to content

Commit 44cb14f

Browse files
authored
Merge pull request #67441 from xedin/fix-overly-eager-closure-resolving
[CSBindings] Prefer conjunctions over closure variables without bindings
2 parents f47c6ac + 11ee82d commit 44cb14f

File tree

3 files changed

+116
-0
lines changed

3 files changed

+116
-0
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,6 +1094,13 @@ bool BindingSet::favoredOverConjunction(Constraint *conjunction) const {
10941094
if (locator->directlyAt<ClosureExpr>()) {
10951095
auto *closure = castToExpr<ClosureExpr>(locator->getAnchor());
10961096

1097+
// If there are no bindings for the closure yet we cannot prioritize
1098+
// it because that runs into risk of missing a result builder transform.
1099+
if (TypeVar->getImpl().isClosureType()) {
1100+
if (Bindings.empty())
1101+
return false;
1102+
}
1103+
10971104
if (auto transform = CS.getAppliedResultBuilderTransform(closure)) {
10981105
// Conjunctions that represent closures with result builder transformed
10991106
// bodies could be attempted right after their resolution if they meet

test/Constraints/issue67363.swift

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking
2+
3+
// https://github.com/apple/swift/issues/67363
4+
5+
protocol UIView {
6+
init()
7+
}
8+
9+
class UILabel : UIView {
10+
required init() {}
11+
}
12+
13+
class UIStackView : UIView {
14+
required init() {}
15+
}
16+
17+
protocol ViewRepresentable {
18+
associatedtype View: UIView
19+
func configure(view: View)
20+
}
21+
22+
struct StyledString: ViewRepresentable {
23+
let content: String
24+
func configure(view: UILabel) {}
25+
}
26+
27+
class StackViewOne<First: UIView>: UIStackView {
28+
var first = First()
29+
}
30+
31+
struct Stack {
32+
struct One<First: ViewRepresentable>: ViewRepresentable {
33+
let first: First
34+
func configure(view: StackViewOne<First.View>) {
35+
first.configure(view: view.first)
36+
}
37+
}
38+
39+
@resultBuilder
40+
enum Builder {
41+
static func buildBlock<First: ViewRepresentable>(_ first: First) -> Stack.One<First> {
42+
Stack.One(first: first)
43+
}
44+
}
45+
46+
static func vertical<StackType: ViewRepresentable>(@Builder build builder: () -> StackType) -> StackType {
47+
builder()
48+
}
49+
}
50+
51+
struct ListItem {
52+
let body: any ViewRepresentable
53+
}
54+
55+
@resultBuilder
56+
enum ListBuilder {
57+
static func buildExpression<View: ViewRepresentable>(_ expression: View?) -> [ListItem?] {
58+
[expression.map { .init(body: $0) }]
59+
}
60+
61+
static func buildBlock(_ components: [ListItem?]...) -> [ListItem] {
62+
components.flatMap { $0.compactMap { $0 } }
63+
}
64+
}
65+
66+
struct WithFooter<T: ViewRepresentable>: ViewRepresentable {
67+
let body: T
68+
let footer: () -> [ListItem]
69+
func configure(view: T.View) {}
70+
}
71+
72+
extension ViewRepresentable {
73+
func withFooter(@ListBuilder build: @escaping () -> [ListItem]) -> WithFooter<Self> {
74+
.init(body: self, footer: build)
75+
}
76+
}
77+
78+
func testThatResultBuilderIsAppliedToWithFooterArgument() -> some ViewRepresentable {
79+
Stack.vertical() {
80+
StyledString(content: "vertical")
81+
}
82+
.withFooter {
83+
StyledString(content: "footer")
84+
}
85+
}

test/expr/closure/multi_statement.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,3 +694,27 @@ func test_recursive_var_reference_in_multistatement_closure() {
694694
}
695695
}
696696
}
697+
698+
// https://github.com/apple/swift/issues/67363
699+
func test_result_builder_in_member_chaining() {
700+
@resultBuilder
701+
struct Builder {
702+
static func buildBlock<T>(_: T) -> Int { 42 }
703+
}
704+
705+
struct Test {
706+
static func test<T>(fn: () -> T) -> T {
707+
fn()
708+
}
709+
710+
func builder(@Builder _: () -> Int) {}
711+
}
712+
713+
Test.test {
714+
let test = Test()
715+
return test
716+
}.builder { // Ok
717+
let result = ""
718+
result
719+
}
720+
}

0 commit comments

Comments
 (0)