Bogus error message mutating OPV struct field of tuple
Zig Version
0.12.0-dev.293+f33bb0228
Steps to Reproduce and Observed Behavior
test {
const S = struct {};
const T = struct { S };
var t: T = undefined;
t[0] = .{};
}
[mlugg@vega help]$ zig test repro.zig
repro.zig:5:10: error: value stored in comptime field does not match the default value of the field
t[0] = .{};
~~~~~^~~~~
Expected Behavior
No error message: this mutation is legal.
S and T are both OPV types. The error does not occur if S contains any non-OPV fields, or if T is struct { void }. It does not occur if T is not a tuple. It does still occur if T contains other, non-zero-bit, fields.
I get an assertion failure on a debug build:
thread 5264 panic: reached unreachable code
Analyzing a.zig: a.zig:test_0
%3 = dbg_block_begin()
%4 = dbg_stmt(2, 5)
%5 = extended(struct_decl(dbg_var, Auto, {}, {}, {}) node_offset:2:15 to :2:24
%6 = dbg_var_val(%5, "S")
%7 = dbg_stmt(3, 5)
%8 = extended(struct_decl(tuple, dbg_var, Auto, {}, {
@"0": {%10, %11},
}) node_offset:3:15 to :3:27
%9 = closure_capture(%5) token_offset:2:11 to :2:12
%12 = dbg_var_val(%8, "T")
%13 = dbg_stmt(4, 5)
%14 = block_comptime({
%15 = break(%14, %8)
}) node_offset:4:12 to :4:13
%16 = alloc_mut(%14) node_offset:4:5 to :4:25
%17 = store_node(%16, @InternPool.Index.undef) node_offset:4:16 to :4:25
%18 = dbg_var_ptr(%16, "t")
%19 = dbg_stmt(5, 5)
%20 = as_node(@InternPool.Index.usize_type, @InternPool.Index.zero) node_offset:5:7 to :5:8
%21 = dbg_stmt(5, 6)
%22 = elem_ptr_node(%16, %20) node_offset:5:5 to :5:9
> %23 = store_node(%22, @InternPool.Index.empty_struct) node_offset:5:5 to :5:15
%24 = dbg_block_end()
%25 = restore_err_ret_index(%2, %4294967211)
%26 = break(%2, @InternPool.Index.void_value)
For full context, use the command
zig ast-check -t a.zig
in a.zig: a.zig:test_0
> %2 = block({%3..%26}) node_offset:1:6 to :1:7
/home/vexu/Documents/zig/zig/lib/std/debug.zig:342:14: 0x82f0e8c in assert (zig)
if (!ok) unreachable; // assertion failure
^
/home/vexu/Documents/zig/zig/src/value.zig:409:15: 0x8408fba in toIntern (zig)
assert(val.ip_index != .none);
^
/home/vexu/Documents/zig/zig/src/value.zig:1429:49: 0x8c6e0a1 in eql (zig)
assert(mod.intern_pool.typeOf(b.toIntern()) == ty.toIntern());
^
/home/vexu/Documents/zig/zig/src/Sema.zig:29376:37: 0x901f33c in storePtrVal (zig)
if (!operand_val.eql(val_ptr.*, operand_ty, mod)) {
^
/home/vexu/Documents/zig/zig/src/Sema.zig:29279:33: 0x8b092bd in storePtr2 (zig)
try sema.storePtrVal(block, src, ptr_val, operand_val, elem_ty);
^
/home/vexu/Documents/zig/zig/src/Sema.zig:5413:26: 0x8c2e972 in zirStoreNode (zig)
return sema.storePtr2(block, src, ptr, ptr_src, operand, operand_src, air_tag);
^
Bug is in comptime pointer mutation: Sema.beginComptimePtrMutation may return un-interned values due to prior mutations, so Sema.storePtrVal should not assume the returned value is interned (but does in the equality check with operand_val). I have a WIP branch which likely resolves this.
also an issue for anonymous structs:
test {
// workaround, explicitly type t: T
// const T = struct { s: u8 };
var t = .{
.s = @as(u8, 0),
};
t.s = 1;
}
$ zig test repo.zig
repo.zig:7:9: error: value stored in comptime field does not match the default value of the field
t.s = 1;
~~~~^~~