From b5c0a797a7f816e502129ad42d5bf19ff84b45e0 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sat, 8 Oct 2022 11:20:39 +0300 Subject: [PATCH] Sema: inline switch capture needs to be set when switch operand is comptime known --- src/Sema.zig | 8 ++++++++ test/behavior/inline_switch.zig | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/Sema.zig b/src/Sema.zig index 6f33180b80..32ea08f697 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -9960,6 +9960,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); extra_index += 1; const body_len = @truncate(u31, sema.code.extra[extra_index]); + const is_inline = sema.code.extra[extra_index] >> 31 != 0; extra_index += 1; const body = sema.code.extra[extra_index..][0..body_len]; extra_index += body_len; @@ -9968,6 +9969,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError // Validation above ensured these will succeed. const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable; if (operand_val.eql(item_val, operand_ty, sema.mod)) { + if (is_inline) child_block.inline_case_capture = operand; + if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand); return sema.resolveBlockBody(block, src, &child_block, body, inst, merges); } @@ -9981,6 +9984,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const ranges_len = sema.code.extra[extra_index]; extra_index += 1; const body_len = @truncate(u31, sema.code.extra[extra_index]); + const is_inline = sema.code.extra[extra_index] >> 31 != 0; extra_index += 1; const items = sema.code.refSlice(extra_index, items_len); extra_index += items_len; @@ -9991,6 +9995,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError // Validation above ensured these will succeed. const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable; if (operand_val.eql(item_val, operand_ty, sema.mod)) { + if (is_inline) child_block.inline_case_capture = operand; + if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand); return sema.resolveBlockBody(block, src, &child_block, body, inst, merges); } @@ -10009,6 +10015,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError if ((try sema.compare(block, src, operand_val, .gte, first_tv.val, operand_ty)) and (try sema.compare(block, src, operand_val, .lte, last_tv.val, operand_ty))) { + if (is_inline) child_block.inline_case_capture = operand; if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand); return sema.resolveBlockBody(block, src, &child_block, body, inst, merges); } @@ -10018,6 +10025,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError } } if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, special.body, operand); + if (special.is_inline) child_block.inline_case_capture = operand; return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges); } diff --git a/test/behavior/inline_switch.zig b/test/behavior/inline_switch.zig index ecc7bba280..153e36ca2f 100644 --- a/test/behavior/inline_switch.zig +++ b/test/behavior/inline_switch.zig @@ -129,3 +129,16 @@ test "inline else int all values" { }, } } + +test "inline switch capture is set when switch operand is comptime known" { + const U2 = union(enum) { + a: u32, + }; + var u: U2 = undefined; + switch (u) { + inline else => |*f, tag| { + try expect(@TypeOf(f) == *u32); + try expect(tag == .a); + }, + } +}