authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-10-26 17:33:35+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-26 14:51:33-04:00
log25012ab3d12ac7bcd4e53a90367afc8e97d91c36
tree23a034934cd1d6ec3676b0d0aca9c092ae7e1b6d
parent17e46a3b97479b13a46a933206fca94d959fafe8

astgen: generate correct switch prong indices

Switch prong values are fetched by index in semantic analysis by prong offset, but these were computed as capture offset. This means that a switch where the first prong does not capture and the second does, the switch_capture zir instruction would be assigned switch_prong 0 instead of 1.

2 files changed, 21 insertions(+), 7 deletions(-)

src/AstGen.zig+7-7
...@@ -6070,6 +6070,13 @@ fn switchExpr(...@@ -6070,6 +6070,13 @@ fn switchExpr(
60706070
6071 var capture_val_scope: Scope.LocalVal = undefined;6071 var capture_val_scope: Scope.LocalVal = undefined;
6072 const sub_scope = blk: {6072 const sub_scope = blk: {
6073 const capture_index = if (is_multi_case) ci: {
6074 multi_case_index += 1;
6075 break :ci multi_case_index - 1;
6076 } else ci: {
6077 scalar_case_index += 1;
6078 break :ci scalar_case_index - 1;
6079 };
6073 const payload_token = case.payload_token orelse break :blk &case_scope.base;6080 const payload_token = case.payload_token orelse break :blk &case_scope.base;
6074 const ident = if (token_tags[payload_token] == .asterisk)6081 const ident = if (token_tags[payload_token] == .asterisk)
6075 payload_token + 16082 payload_token + 1
...@@ -6103,13 +6110,6 @@ fn switchExpr(...@@ -6103,13 +6110,6 @@ fn switchExpr(
6103 0b10 => .switch_capture_multi,6110 0b10 => .switch_capture_multi,
6104 0b11 => .switch_capture_multi_ref,6111 0b11 => .switch_capture_multi_ref,
6105 };6112 };
6106 const capture_index = if (is_multi_case) ci: {
6107 multi_case_index += 1;
6108 break :ci multi_case_index - 1;
6109 } else ci: {
6110 scalar_case_index += 1;
6111 break :ci scalar_case_index - 1;
6112 };
6113 break :capture try case_scope.add(.{6113 break :capture try case_scope.add(.{
6114 .tag = capture_tag,6114 .tag = capture_tag,
6115 .data = .{ .switch_capture = .{6115 .data = .{ .switch_capture = .{
test/behavior/switch.zig+14
...@@ -299,3 +299,17 @@ fn testSwitchHandleAllCasesRange(x: u8) u8 {...@@ -299,3 +299,17 @@ fn testSwitchHandleAllCasesRange(x: u8) u8 {
299 204...255 => 3,299 204...255 => 3,
300 };300 };
301}301}
302
303test "switch on union with some prongs capturing" {
304 const X = union(enum) {
305 a,
306 b: i32,
307 };
308
309 var x: X = X{ .b = 10 };
310 var y: i32 = switch (x) {
311 .a => unreachable,
312 .b => |b| b + 1,
313 };
314 try expect(y == 11);
315}