Skip to content

Commit 3add375

Browse files
committed
[BuilderTransform] Case: Save result of buildBlock into a variable before using in buildEither
Fixes implementation issue where build block is type-checked as part of `buildEither(...)`. This is incorrect according to the original proposal (SE-0289), `buildBlock` should be type-checked independently and `buildEither` should have no effect on what overload of `buildBlock` gets selected.
1 parent 7c258f2 commit 3add375

File tree

2 files changed

+42
-2
lines changed

2 files changed

+42
-2
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,8 @@ class ResultBuilderTransform
261261
}
262262

263263
std::pair<NullablePtr<Expr>, std::optional<UnsupportedElt>>
264-
transform(BraceStmt *braceStmt, SmallVectorImpl<ASTNode> &newBody) {
264+
transform(BraceStmt *braceStmt, SmallVectorImpl<ASTNode> &newBody,
265+
bool isolateBuildBlock = false) {
265266
SmallVector<Expr *, 4> buildBlockArguments;
266267

267268
auto failTransform = [&](UnsupportedElt unsupported) {
@@ -326,6 +327,14 @@ class ResultBuilderTransform
326327
auto *buildBlock = builder.buildCall(
327328
braceStmt->getStartLoc(), ctx.Id_buildBlock, buildBlockArguments,
328329
/*argLabels=*/{});
330+
331+
if (isolateBuildBlock) {
332+
auto *buildBlockVar = captureExpr(buildBlock, newBody);
333+
return std::make_pair(
334+
builder.buildVarRef(buildBlockVar, braceStmt->getStartLoc()),
335+
std::nullopt);
336+
}
337+
329338
return std::make_pair(buildBlock, std::nullopt);
330339
}
331340
}
@@ -634,7 +643,8 @@ class ResultBuilderTransform
634643
std::optional<UnsupportedElt> unsupported;
635644
SmallVector<ASTNode, 4> newBody;
636645

637-
std::tie(caseVarRef, unsupported) = transform(body, newBody);
646+
std::tie(caseVarRef, unsupported) =
647+
transform(body, newBody, /*isolateBuildBlock=*/true);
638648

639649
if (unsupported) {
640650
recordUnsupported(*unsupported);

test/Constraints/result_builder_switch_with_vars.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,33 @@ tuplify {
9090
value.a
9191
}
9292
}
93+
94+
tuplify { _ in
95+
switch true {
96+
// CHECK: (case_stmt {{.*}}
97+
// CHECK: (pattern_named implicit type="Int" "$__builder2")
98+
// CHECK: (declref_expr implicit type="(TupleBuilder.Type) -> (Int) -> Int" location={{.*}} range={{.*}} decl="{{.*}}buildBlock@{{.*}}" function_ref=single apply)
99+
100+
// CHECK: (call_expr implicit type="Either<Int, Int>" {{.*}}
101+
// CHECK-NEXT: (dot_syntax_call_expr implicit type="(Int) -> Either<Int, Int>" {{.*}}
102+
// CHECK-NEXT: (declref_expr implicit type="(TupleBuilder.Type) -> (Int) -> Either<Int, Int>" location={{.*}} range={{.*}} decl="{{.*}}buildEither(first:)@{{.*}}" function_ref=single apply)
103+
// CHECK: (argument_list implicit labels="first:"
104+
// CHECK-NEXT: (argument label="first"
105+
// CHECK-NEXT: (load_expr implicit type="Int" {{.*}}
106+
// CHECK-NEXT: (declref_expr implicit type="@lvalue Int" location={{.*}} range={{.*}} decl="{{.*}}.$__builder2@{{.*}}" function_ref=unapplied))))))))
107+
case true: 0
108+
109+
// CHECK: (case_stmt {{.*}}
110+
// CHECK: (pattern_named implicit type="Int" "$__builder4")
111+
// CHECK: (declref_expr implicit type="(TupleBuilder.Type) -> (Int) -> Int" location={{.*}} range={{.*}} decl="{{.*}}buildBlock@{{.*}}" function_ref=single apply)
112+
113+
// CHECK: (call_expr implicit type="Either<Int, Int>" {{.*}}
114+
// CHECK-NEXT: (dot_syntax_call_expr implicit type="(Int) -> Either<Int, Int>" {{.*}}
115+
// CHECK-NEXT: (declref_expr implicit type="(TupleBuilder.Type) -> (Int) -> Either<Int, Int>" location={{.*}} range={{.*}} decl="{{.*}}buildEither(second:)@{{.*}}" function_ref=single apply)
116+
// CHECK: (argument_list implicit labels="second:"
117+
// CHECK-NEXT: (argument label="second"
118+
// CHECK-NEXT: (load_expr implicit type="Int" {{.*}}
119+
// CHECK-NEXT: (declref_expr implicit type="@lvalue Int" location={{.*}} range={{.*}} decl="{{.*}}.$__builder4@{{.*}}" function_ref=unapplied))))))))
120+
case false: 1
121+
}
122+
}

0 commit comments

Comments
 (0)