| author | |
| committer | |
| log | 03c363300fd829f3a656c6a9854a9c9720c9b3f1 |
| tree | 9cf60f26f2d44e9527fac310102fdb80e085d100 |
| parent | 0001f91e4e1e51cd64cdd5c0a21451c8bad67233 |
`break`ing from something which isn't a loop should always be opt-in.
This was a bug in #21257.2 files changed, 19 insertions(+), 2 deletions(-)
lib/std/zig/AstGen.zig+2-2| ... | @@ -7811,9 +7811,7 @@ fn switchExpr( | ... | @@ -7811,9 +7811,7 @@ fn switchExpr( |
| 7811 | const switch_block = try parent_gz.makeBlockInst(switch_tag, node); | 7811 | const switch_block = try parent_gz.makeBlockInst(switch_tag, node); |
| 7812 | 7812 | ||
| 7813 | if (switch_full.label_token) |label_token| { | 7813 | if (switch_full.label_token) |label_token| { |
| 7814 | block_scope.break_block = switch_block.toOptional(); | ||
| 7815 | block_scope.continue_block = switch_block.toOptional(); | 7814 | block_scope.continue_block = switch_block.toOptional(); |
| 7816 | // `break_result_info` already set above | ||
| 7817 | block_scope.continue_result_info = .{ | 7815 | block_scope.continue_result_info = .{ |
| 7818 | .rl = if (any_payload_is_ref) | 7816 | .rl = if (any_payload_is_ref) |
| 7819 | .{ .ref_coerced_ty = raw_operand_ty_ref } | 7817 | .{ .ref_coerced_ty = raw_operand_ty_ref } |
| ... | @@ -7825,6 +7823,8 @@ fn switchExpr( | ... | @@ -7825,6 +7823,8 @@ fn switchExpr( |
| 7825 | .token = label_token, | 7823 | .token = label_token, |
| 7826 | .block_inst = switch_block, | 7824 | .block_inst = switch_block, |
| 7827 | }; | 7825 | }; |
| 7826 | // `break` can target this via `label.block_inst` | ||
| 7827 | // `break_result_info` already set by `setBreakResultInfo` | ||
| 7828 | } | 7828 | } |
| 7829 | 7829 | ||
| 7830 | // We re-use this same scope for all cases, including the special prong, if any. | 7830 | // We re-use this same scope for all cases, including the special prong, if any. |
test/behavior/switch.zig+17| ... | @@ -985,3 +985,20 @@ test "labeled switch with break" { | ... | @@ -985,3 +985,20 @@ test "labeled switch with break" { |
| 985 | 985 | ||
| 986 | comptime assert(comptime_val); | 986 | comptime assert(comptime_val); |
| 987 | } | 987 | } |
| 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 | } |