Skip to content

Commit f892189

Browse files
committed
[Result builder transform] Don't abort when we encounter a case with no statements
Remove code that aborts the result builder transform when we encounter a case that has no statements in it. This can occur when the only statements were behind a `#if` that evaluataed empty, so it should not cause an abort. Previously, the presence of an IfConfigDecl within the case statement would have prevented us from aborting the traversal here. However, the removal of IfConfigDecl from the AST turned this previously-accepted code into a compiler crash. Fixes rdar://139312426.
1 parent 3f8ffaa commit f892189

File tree

2 files changed

+41
-13
lines changed

2 files changed

+41
-13
lines changed

Diff for: lib/Sema/BuilderTransform.cpp

-13
Original file line numberDiff line numberDiff line change
@@ -630,19 +630,6 @@ class ResultBuilderTransform
630630
transformCase(CaseStmt *caseStmt) {
631631
auto *body = caseStmt->getBody();
632632

633-
// Explicitly disallow `case` statements with empty bodies
634-
// since that helps to diagnose other issues with switch
635-
// statements by excluding invalid cases.
636-
if (auto *BS = dyn_cast<BraceStmt>(body)) {
637-
if (BS->getNumElements() == 0) {
638-
// HACK: still allow empty bodies if typechecking for code
639-
// completion. Code completion ignores diagnostics
640-
// and won't get any types if we fail.
641-
if (!ctx.SourceMgr.hasIDEInspectionTargetBuffer())
642-
return std::nullopt;
643-
}
644-
}
645-
646633
NullablePtr<Expr> caseVarRef;
647634
std::optional<UnsupportedElt> unsupported;
648635
SmallVector<ASTNode, 4> newBody;

Diff for: test/Constraints/result_builder_empty_case.swift

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// RUN: %target-swift-emit-silgen %s -verify | %FileCheck %s
2+
3+
// Tests for a crash that occurred when the result builder transform encountered
4+
// an empty case statement.
5+
protocol V { }
6+
7+
struct EV: V { }
8+
9+
@resultBuilder
10+
struct VB {
11+
static func buildBlock(_ components: any V...) -> any V { EV() }
12+
static func buildEither(first: any V) -> any V { first }
13+
static func buildEither(second: any V) -> any V { second }
14+
}
15+
16+
extension String: V { }
17+
18+
enum E {
19+
case a(Int)
20+
case b(String)
21+
}
22+
23+
struct S {
24+
var flag: E
25+
26+
// CHECK-LABEL: sil hidden [ossa] @$s25result_builder_empty_case1SV4testAA1V_pyF
27+
// CHECK: switch_enum
28+
@VB
29+
func test() -> any V {
30+
switch flag {
31+
case .a:
32+
// When NOT_DEFINED is... not defined... this ends up being an empty case.
33+
// We permit this
34+
#if NOT_DEFINED
35+
EV()
36+
#endif
37+
case .b:
38+
EV()
39+
}
40+
}
41+
}

0 commit comments

Comments
 (0)