Commit 97dc5f6eb5
Changed files (3)
src
test
behavior
src/Sema.zig
@@ -396,6 +396,14 @@ pub const Block = struct {
return result_index;
}
+ fn addUnreachable(block: *Block, src: LazySrcLoc, safety_check: bool) !void {
+ if (safety_check and block.wantSafety()) {
+ _ = try block.sema.safetyPanic(block, src, .unreach);
+ } else {
+ _ = try block.addNoOp(.unreach);
+ }
+ }
+
pub fn startAnonDecl(block: *Block) !WipAnonDecl {
return WipAnonDecl{
.block = block,
@@ -6371,14 +6379,22 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
}
var final_else_body: []const Air.Inst.Index = &.{};
- if (special.body.len != 0) {
+ if (special.body.len != 0 or !is_first) {
var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, child_block.wip_capture_scope);
defer wip_captures.deinit();
case_block.instructions.shrinkRetainingCapacity(0);
case_block.wip_capture_scope = wip_captures.scope;
- _ = try sema.analyzeBody(&case_block, special.body);
+ if (special.body.len != 0) {
+ _ = try sema.analyzeBody(&case_block, special.body);
+ } else {
+ // We still need a terminator in this block, but we have proven
+ // that it is unreachable.
+ // TODO this should be a special safety panic other than unreachable, something
+ // like "panic: switch operand had corrupt value not allowed by the type"
+ try case_block.addUnreachable(src, true);
+ }
try wip_captures.finalize();
@@ -8963,15 +8979,10 @@ fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
const inst_data = sema.code.instructions.items(.data)[inst].@"unreachable";
const src = inst_data.src();
- const safety_check = inst_data.safety;
try sema.requireRuntimeBlock(block, src);
// TODO Add compile error for @optimizeFor occurring too late in a scope.
- if (safety_check and block.wantSafety()) {
- return sema.safetyPanic(block, src, .unreach);
- } else {
- _ = try block.addNoOp(.unreach);
- return always_noreturn;
- }
+ try block.addUnreachable(src, inst_data.safety);
+ return always_noreturn;
}
fn zirRetErrValue(
test/behavior/switch.zig
@@ -262,3 +262,40 @@ fn testSwitchEnumPtrCapture() !void {
else => unreachable,
}
}
+
+test "switch handles all cases of number" {
+ try testSwitchHandleAllCases();
+ comptime try testSwitchHandleAllCases();
+}
+
+fn testSwitchHandleAllCases() !void {
+ try expect(testSwitchHandleAllCasesExhaustive(0) == 3);
+ try expect(testSwitchHandleAllCasesExhaustive(1) == 2);
+ try expect(testSwitchHandleAllCasesExhaustive(2) == 1);
+ try expect(testSwitchHandleAllCasesExhaustive(3) == 0);
+
+ try expect(testSwitchHandleAllCasesRange(100) == 0);
+ try expect(testSwitchHandleAllCasesRange(200) == 1);
+ try expect(testSwitchHandleAllCasesRange(201) == 2);
+ try expect(testSwitchHandleAllCasesRange(202) == 4);
+ try expect(testSwitchHandleAllCasesRange(230) == 3);
+}
+
+fn testSwitchHandleAllCasesExhaustive(x: u2) u2 {
+ return switch (x) {
+ 0 => @as(u2, 3),
+ 1 => 2,
+ 2 => 1,
+ 3 => 0,
+ };
+}
+
+fn testSwitchHandleAllCasesRange(x: u8) u8 {
+ return switch (x) {
+ 0...100 => @as(u8, 0),
+ 101...200 => 1,
+ 201, 203 => 2,
+ 202 => 4,
+ 204...255 => 3,
+ };
+}
test/behavior/switch_stage1.zig
@@ -3,43 +3,6 @@ const expect = std.testing.expect;
const expectError = std.testing.expectError;
const expectEqual = std.testing.expectEqual;
-test "switch handles all cases of number" {
- try testSwitchHandleAllCases();
- comptime try testSwitchHandleAllCases();
-}
-
-fn testSwitchHandleAllCases() !void {
- try expect(testSwitchHandleAllCasesExhaustive(0) == 3);
- try expect(testSwitchHandleAllCasesExhaustive(1) == 2);
- try expect(testSwitchHandleAllCasesExhaustive(2) == 1);
- try expect(testSwitchHandleAllCasesExhaustive(3) == 0);
-
- try expect(testSwitchHandleAllCasesRange(100) == 0);
- try expect(testSwitchHandleAllCasesRange(200) == 1);
- try expect(testSwitchHandleAllCasesRange(201) == 2);
- try expect(testSwitchHandleAllCasesRange(202) == 4);
- try expect(testSwitchHandleAllCasesRange(230) == 3);
-}
-
-fn testSwitchHandleAllCasesExhaustive(x: u2) u2 {
- return switch (x) {
- 0 => @as(u2, 3),
- 1 => 2,
- 2 => 1,
- 3 => 0,
- };
-}
-
-fn testSwitchHandleAllCasesRange(x: u8) u8 {
- return switch (x) {
- 0...100 => @as(u8, 0),
- 101...200 => 1,
- 201, 203 => 2,
- 202 => 4,
- 204...255 => 3,
- };
-}
-
test "switch all prongs unreachable" {
try testAllProngsUnreachable();
comptime try testAllProngsUnreachable();