mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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.
This commit is contained in:
@@ -630,19 +630,6 @@ protected:
|
||||
transformCase(CaseStmt *caseStmt) {
|
||||
auto *body = caseStmt->getBody();
|
||||
|
||||
// Explicitly disallow `case` statements with empty bodies
|
||||
// since that helps to diagnose other issues with switch
|
||||
// statements by excluding invalid cases.
|
||||
if (auto *BS = dyn_cast<BraceStmt>(body)) {
|
||||
if (BS->getNumElements() == 0) {
|
||||
// HACK: still allow empty bodies if typechecking for code
|
||||
// completion. Code completion ignores diagnostics
|
||||
// and won't get any types if we fail.
|
||||
if (!ctx.SourceMgr.hasIDEInspectionTargetBuffer())
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
NullablePtr<Expr> caseVarRef;
|
||||
std::optional<UnsupportedElt> unsupported;
|
||||
SmallVector<ASTNode, 4> newBody;
|
||||
|
||||
41
test/Constraints/result_builder_empty_case.swift
Normal file
41
test/Constraints/result_builder_empty_case.swift
Normal file
@@ -0,0 +1,41 @@
|
||||
// RUN: %target-swift-emit-silgen %s -verify | %FileCheck %s
|
||||
|
||||
// Tests for a crash that occurred when the result builder transform encountered
|
||||
// an empty case statement.
|
||||
protocol V { }
|
||||
|
||||
struct EV: V { }
|
||||
|
||||
@resultBuilder
|
||||
struct VB {
|
||||
static func buildBlock(_ components: any V...) -> any V { EV() }
|
||||
static func buildEither(first: any V) -> any V { first }
|
||||
static func buildEither(second: any V) -> any V { second }
|
||||
}
|
||||
|
||||
extension String: V { }
|
||||
|
||||
enum E {
|
||||
case a(Int)
|
||||
case b(String)
|
||||
}
|
||||
|
||||
struct S {
|
||||
var flag: E
|
||||
|
||||
// CHECK-LABEL: sil hidden [ossa] @$s25result_builder_empty_case1SV4testAA1V_pyF
|
||||
// CHECK: switch_enum
|
||||
@VB
|
||||
func test() -> any V {
|
||||
switch flag {
|
||||
case .a:
|
||||
// When NOT_DEFINED is... not defined... this ends up being an empty case.
|
||||
// We permit this
|
||||
#if NOT_DEFINED
|
||||
EV()
|
||||
#endif
|
||||
case .b:
|
||||
EV()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user