Skip to content

Commit ee50783

Browse files
authored
Merge pull request #39575 from apple/set-types-for-case-vars
[ResultBuilders] Make sure that `case` body variables get types
2 parents 88ad3b7 + b8ea5e7 commit ee50783

File tree

2 files changed

+106
-1
lines changed

2 files changed

+106
-1
lines changed

Diff for: lib/Sema/BuilderTransform.cpp

+18-1
Original file line numberDiff line numberDiff line change
@@ -1462,6 +1462,14 @@ class BuilderClosureRewriter
14621462
return nullptr;
14631463
}
14641464

1465+
// Setup the types of our case body var decls.
1466+
for (auto *expected : caseStmt->getCaseBodyVariablesOrEmptyArray()) {
1467+
assert(expected->hasName());
1468+
auto prev = expected->getParentVarDecl();
1469+
auto type = solution.resolveInterfaceType(solution.getType(prev));
1470+
expected->setInterfaceType(type);
1471+
}
1472+
14651473
// Transform the body of the case.
14661474
auto body = cast<BraceStmt>(caseStmt->getBody());
14671475
auto captured = takeCapturedStmt(body);
@@ -1721,7 +1729,16 @@ Optional<BraceStmt *> TypeChecker::applyResultBuilderBodyTransform(
17211729
solutions.front(),
17221730
SolutionApplicationTarget(func))) {
17231731
performSyntacticDiagnosticsForTarget(*result, /*isExprStmt*/ false);
1724-
return result->getFunctionBody();
1732+
auto *body = result->getFunctionBody();
1733+
1734+
if (cs.isDebugMode()) {
1735+
auto &log = llvm::errs();
1736+
log << "--- Type-checked function body ---\n";
1737+
body->dump(log);
1738+
log << '\n';
1739+
}
1740+
1741+
return body;
17251742
}
17261743

17271744
return nullptr;
+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// RUN: %target-swift-frontend -typecheck -dump-ast %s | %FileCheck %s
2+
3+
enum Either<T,U> {
4+
case first(T)
5+
case second(U)
6+
}
7+
8+
@resultBuilder
9+
struct TupleBuilder {
10+
static func buildBlock<T1>(_ t1: T1) -> (T1) {
11+
return (t1)
12+
}
13+
14+
static func buildBlock<T1, T2>(_ t1: T1, _ t2: T2) -> (T1, T2) {
15+
return (t1, t2)
16+
}
17+
18+
static func buildBlock<T1, T2, T3>(_ t1: T1, _ t2: T2, _ t3: T3)
19+
-> (T1, T2, T3) {
20+
return (t1, t2, t3)
21+
}
22+
23+
static func buildBlock<T1, T2, T3, T4>(_ t1: T1, _ t2: T2, _ t3: T3, _ t4: T4)
24+
-> (T1, T2, T3, T4) {
25+
return (t1, t2, t3, t4)
26+
}
27+
28+
static func buildBlock<T1, T2, T3, T4, T5>(
29+
_ t1: T1, _ t2: T2, _ t3: T3, _ t4: T4, _ t5: T5
30+
) -> (T1, T2, T3, T4, T5) {
31+
return (t1, t2, t3, t4, t5)
32+
}
33+
34+
static func buildEither<T,U>(first value: T) -> Either<T,U> {
35+
return .first(value)
36+
}
37+
static func buildEither<T,U>(second value: U) -> Either<T,U> {
38+
return .second(value)
39+
}
40+
}
41+
42+
enum E {
43+
case test(a: String, b: Int)
44+
}
45+
46+
func tuplify<T>(@TupleBuilder body: (E) throws -> T) rethrows {
47+
}
48+
49+
tuplify {
50+
switch $0 {
51+
// CHECK: (case_body_variables
52+
// CHECK-NEXT: (var_decl implicit {{.*}} "a" type='String' interface type='String' let readImpl=stored immutable)
53+
// CHECK-NEXT: (var_decl implicit {{.*}} "b" type='Int' interface type='Int' let readImpl=stored immutable)
54+
case let .test(a, b):
55+
a
56+
b
57+
}
58+
59+
switch $0 {
60+
// CHECK: (case_body_variables
61+
// CHECK-NEXT: (var_decl implicit {{.*}} "a" type='String' interface type='String' let readImpl=stored immutable)
62+
// CHECK-NEXT: (var_decl implicit {{.*}} "b" type='Int' interface type='Int' let readImpl=stored immutable)
63+
case .test(let a, let b):
64+
a
65+
b
66+
}
67+
68+
switch $0 {
69+
// CHECK: (case_body_variables
70+
// CHECK-NEXT: (var_decl implicit {{.*}} "value" type='(a: String, b: Int)' interface type='(a: String, b: Int)' let readImpl=stored immutable)
71+
case let .test((value)):
72+
value.a
73+
}
74+
75+
switch $0 {
76+
// CHECK: (case_body_variables
77+
// CHECK-NEXT: (var_decl implicit {{.*}} "value" type='(a: String, b: Int)' interface type='(a: String, b: Int)' let readImpl=stored immutable)
78+
case let .test(value):
79+
value.a
80+
}
81+
82+
switch $0 {
83+
// CHECK: (case_body_variables
84+
// CHECK-NEXT: (var_decl implicit {{.*}} "value" type='(a: String, b: Int)' interface type='(a: String, b: Int)' let readImpl=stored immutable)
85+
case .test(let value):
86+
value.a
87+
}
88+
}

0 commit comments

Comments
 (0)