Skip to content

Commit 9ce93da

Browse files
committed
AstGen: do not allow unlabeled break to exit a labeled switch
`break`ing from something which isn't a loop should always be opt-in. This was a bug in ziglang#21257.
1 parent b95e0e0 commit 9ce93da

File tree

2 files changed

+19
-2
lines changed

2 files changed

+19
-2
lines changed

lib/std/zig/AstGen.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7811,9 +7811,7 @@ fn switchExpr(
78117811
const switch_block = try parent_gz.makeBlockInst(switch_tag, node);
78127812

78137813
if (switch_full.label_token) |label_token| {
7814-
block_scope.break_block = switch_block.toOptional();
78157814
block_scope.continue_block = switch_block.toOptional();
7816-
// `break_result_info` already set above
78177815
block_scope.continue_result_info = .{
78187816
.rl = if (any_payload_is_ref)
78197817
.{ .ref_coerced_ty = raw_operand_ty_ref }
@@ -7825,6 +7823,8 @@ fn switchExpr(
78257823
.token = label_token,
78267824
.block_inst = switch_block,
78277825
};
7826+
// `break` can target this via `label.block_inst`
7827+
// `break_result_info` already set by `setBreakResultInfo`
78287828
}
78297829

78307830
// We re-use this same scope for all cases, including the special prong, if any.

test/behavior/switch.zig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -985,3 +985,20 @@ test "labeled switch with break" {
985985

986986
comptime assert(comptime_val);
987987
}
988+
989+
test "unlabeled break ignores switch" {
990+
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
991+
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
992+
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
993+
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
994+
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
995+
996+
const result = while (true) {
997+
_ = s: switch (@as(u32, 1)) {
998+
1 => continue :s 123,
999+
else => |x| break x,
1000+
};
1001+
comptime unreachable; // control flow never breaks from the switch
1002+
};
1003+
try expect(result == 123);
1004+
}

0 commit comments

Comments
 (0)