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...@@ -9960,6 +9960,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
9960 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);9960 const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
9961 extra_index += 1;9961 extra_index += 1;
9962 const body_len = @truncate(u31, sema.code.extra[extra_index]);9962 const body_len = @truncate(u31, sema.code.extra[extra_index]);
9963 const is_inline = sema.code.extra[extra_index] >> 31 != 0;
9963 extra_index += 1;9964 extra_index += 1;
9964 const body = sema.code.extra[extra_index..][0..body_len];9965 const body = sema.code.extra[extra_index..][0..body_len];
9965 extra_index += body_len;9966 extra_index += body_len;
...@@ -9968,6 +9969,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -9968,6 +9969,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
9968 // Validation above ensured these will succeed.9969 // Validation above ensured these will succeed.
9969 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable;9970 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable;
9970 if (operand_val.eql(item_val, operand_ty, sema.mod)) {9971 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
9972 if (is_inline) child_block.inline_case_capture = operand;
9973
9971 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);9974 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
9972 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);9975 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
9973 }9976 }
...@@ -9981,6 +9984,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -9981,6 +9984,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
9981 const ranges_len = sema.code.extra[extra_index];9984 const ranges_len = sema.code.extra[extra_index];
9982 extra_index += 1;9985 extra_index += 1;
9983 const body_len = @truncate(u31, sema.code.extra[extra_index]);9986 const body_len = @truncate(u31, sema.code.extra[extra_index]);
9987 const is_inline = sema.code.extra[extra_index] >> 31 != 0;
9984 extra_index += 1;9988 extra_index += 1;
9985 const items = sema.code.refSlice(extra_index, items_len);9989 const items = sema.code.refSlice(extra_index, items_len);
9986 extra_index += items_len;9990 extra_index += items_len;
...@@ -9991,6 +9995,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -9991,6 +9995,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
9991 // Validation above ensured these will succeed.9995 // Validation above ensured these will succeed.
9992 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable;9996 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable;
9993 if (operand_val.eql(item_val, operand_ty, sema.mod)) {9997 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
9998 if (is_inline) child_block.inline_case_capture = operand;
9999
9994 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);10000 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
9995 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);10001 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
9996 }10002 }
...@@ -10009,6 +10015,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10009,6 +10015,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10009 if ((try sema.compare(block, src, operand_val, .gte, first_tv.val, operand_ty)) and10015 if ((try sema.compare(block, src, operand_val, .gte, first_tv.val, operand_ty)) and
10010 (try sema.compare(block, src, operand_val, .lte, last_tv.val, operand_ty)))10016 (try sema.compare(block, src, operand_val, .lte, last_tv.val, operand_ty)))
10011 {10017 {
10018 if (is_inline) child_block.inline_case_capture = operand;
10012 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);10019 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
10013 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);10020 return sema.resolveBlockBody(block, src, &child_block, body, inst, merges);
10014 }10021 }
...@@ -10018,6 +10025,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10018,6 +10025,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10018 }10025 }
10019 }10026 }
10020 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, special.body, operand);10027 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, special.body, operand);
10028 if (special.is_inline) child_block.inline_case_capture = operand;
10021 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);10029 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);
10022 }10030 }
1002310031
test/behavior/inline_switch.zig+13
...@@ -129,3 +129,16 @@ test "inline else int all values" {...@@ -129,3 +129,16 @@ test "inline else int all values" {
129 },129 },
130 }130 }
131}131}
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}