diff --git a/lib/Sema/BuilderTransform.cpp b/lib/Sema/BuilderTransform.cpp index ea3688a2894..6e2d6a43828 100644 --- a/lib/Sema/BuilderTransform.cpp +++ b/lib/Sema/BuilderTransform.cpp @@ -261,7 +261,8 @@ protected: } std::pair, std::optional> - transform(BraceStmt *braceStmt, SmallVectorImpl &newBody) { + transform(BraceStmt *braceStmt, SmallVectorImpl &newBody, + bool isolateBuildBlock = false) { SmallVector buildBlockArguments; auto failTransform = [&](UnsupportedElt unsupported) { @@ -326,6 +327,14 @@ protected: auto *buildBlock = builder.buildCall( braceStmt->getStartLoc(), ctx.Id_buildBlock, buildBlockArguments, /*argLabels=*/{}); + + if (isolateBuildBlock) { + auto *buildBlockVar = captureExpr(buildBlock, newBody); + return std::make_pair( + builder.buildVarRef(buildBlockVar, braceStmt->getStartLoc()), + std::nullopt); + } + return std::make_pair(buildBlock, std::nullopt); } } @@ -634,7 +643,8 @@ protected: std::optional unsupported; SmallVector newBody; - std::tie(caseVarRef, unsupported) = transform(body, newBody); + std::tie(caseVarRef, unsupported) = + transform(body, newBody, /*isolateBuildBlock=*/true); if (unsupported) { recordUnsupported(*unsupported); diff --git a/test/Constraints/result_builder_switch_with_vars.swift b/test/Constraints/result_builder_switch_with_vars.swift index a4bf5575557..3ff736279e0 100644 --- a/test/Constraints/result_builder_switch_with_vars.swift +++ b/test/Constraints/result_builder_switch_with_vars.swift @@ -90,3 +90,33 @@ tuplify { value.a } } + +tuplify { _ in + switch true { + // CHECK: (case_stmt {{.*}} + // CHECK: (pattern_named implicit type="Int" "$__builder2") + // CHECK: (declref_expr implicit type="(TupleBuilder.Type) -> (Int) -> Int" location={{.*}} range={{.*}} decl="{{.*}}buildBlock@{{.*}}" function_ref=single apply) + + // CHECK: (call_expr implicit type="Either" {{.*}} + // CHECK-NEXT: (dot_syntax_call_expr implicit type="(Int) -> Either" {{.*}} + // CHECK-NEXT: (declref_expr implicit type="(TupleBuilder.Type) -> (Int) -> Either" location={{.*}} range={{.*}} decl="{{.*}}buildEither(first:)@{{.*}}" function_ref=single apply) + // CHECK: (argument_list implicit labels="first:" + // CHECK-NEXT: (argument label="first" + // CHECK-NEXT: (load_expr implicit type="Int" {{.*}} + // CHECK-NEXT: (declref_expr implicit type="@lvalue Int" location={{.*}} range={{.*}} decl="{{.*}}.$__builder2@{{.*}}" function_ref=unapplied)))))))) + case true: 0 + + // CHECK: (case_stmt {{.*}} + // CHECK: (pattern_named implicit type="Int" "$__builder4") + // CHECK: (declref_expr implicit type="(TupleBuilder.Type) -> (Int) -> Int" location={{.*}} range={{.*}} decl="{{.*}}buildBlock@{{.*}}" function_ref=single apply) + + // CHECK: (call_expr implicit type="Either" {{.*}} + // CHECK-NEXT: (dot_syntax_call_expr implicit type="(Int) -> Either" {{.*}} + // CHECK-NEXT: (declref_expr implicit type="(TupleBuilder.Type) -> (Int) -> Either" location={{.*}} range={{.*}} decl="{{.*}}buildEither(second:)@{{.*}}" function_ref=single apply) + // CHECK: (argument_list implicit labels="second:" + // CHECK-NEXT: (argument label="second" + // CHECK-NEXT: (load_expr implicit type="Int" {{.*}} + // CHECK-NEXT: (declref_expr implicit type="@lvalue Int" location={{.*}} range={{.*}} decl="{{.*}}.$__builder4@{{.*}}" function_ref=unapplied)))))))) + case false: 1 + } +}