authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-10-08 11:20:39+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-10-08 16:58:52+03:00
logb5c0a797a7f816e502129ad42d5bf19ff84b45e0
tree360265994fde21212726ba9d030f899d8f7f9be5
parent1500b9ddc3579a0581eb97b71da9baf30fb9149c

Sema: inline switch capture needs to be set when switch operand is comptime known


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

src/Sema.zig+8
......@@ -9960,6 +9960,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
99609960 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
99619961 extra_index += 1;
99629962 const body_len = @truncate(u31, sema.code.extra[extra_index]);
9963 const is_inline = sema.code.extra[extra_index] >> 31 != 0;
99639964 extra_index += 1;
99649965 const body = sema.code.extra[extra_index..][0..body_len];
99659966 extra_index += body_len;
......@@ -9968,6 +9969,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
99689969 // Validation above ensured these will succeed.
99699970 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable;
99709971 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
9972 if (is_inline) child_block.inline_case_capture = operand;
9973
99719974 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
99729975 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
99739976 }
......@@ -9981,6 +9984,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
99819984 const ranges_len = sema.code.extra[extra_index];
99829985 extra_index += 1;
99839986 const body_len = @truncate(u31, sema.code.extra[extra_index]);
9987 const is_inline = sema.code.extra[extra_index] >> 31 != 0;
99849988 extra_index += 1;
99859989 const items = sema.code.refSlice(extra_index, items_len);
99869990 extra_index += items_len;
......@@ -9991,6 +9995,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
99919995 // Validation above ensured these will succeed.
99929996 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable;
99939997 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
9998 if (is_inline) child_block.inline_case_capture = operand;
9999
999410000 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
999510001 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
999610002 }
......@@ -10009,6 +10015,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1000910015 if ((try sema.compare(block, src, operand_val, .gte, first_tv.val, operand_ty)) and
1001010016 (try sema.compare(block, src, operand_val, .lte, last_tv.val, operand_ty)))
1001110017 {
10018 if (is_inline) child_block.inline_case_capture = operand;
1001210019 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
1001310020 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
1001410021 }
......@@ -10018,6 +10025,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1001810025 }
1001910026 }
1002010027 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, special.body, operand);
10028 if (special.is_inline) child_block.inline_case_capture = operand;
1002110029 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);
1002210030 }
1002310031
test/behavior/inline_switch.zig+13
......@@ -129,3 +129,16 @@ test "inline else int all values" {
129129 },
130130 }
131131}
132
133test "inline switch capture is set when switch operand is comptime known" {
134 const U2 = union(enum) {
135 a: u32,
136 };
137 var u: U2 = undefined;
138 switch (u) {
139 inline else => |*f, tag| {
140 try expect(@TypeOf(f) == *u32);
141 try expect(tag == .a);
142 },
143 }
144}