Referring to same struct field during reassignment

I’m seeing something I didn’t expect (zig 0.15.2):

pub const Count = struct {
    first: usize = 0,
    second: usize = 0,
};
    std.debug.print("before: {any}\n", .{e.cmd.count});
    e.cmd.count = .{ .first = 0, .second = e.cmd.count.first };
    std.debug.print("after: {any}\n", .{e.cmd.count});
before: .{ .first = 3, .second = 0 }
after: .{ .first = 0, .second = 0 }

So it seems count.first is already assigned during object construction and count.second will hold an invalid value.

This instead works:

    std.debug.print("before: {any}\n", .{e.cmd.count});
    e.cmd.count.second = e.cmd.count.first;
    e.cmd.count.first = 0;
    std.debug.print("after: {any}\n", .{e.cmd.count});
before: .{ .first = 3, .second = 0 }
after: .{ .first = 0, .second = 3 }

Is it so by design?

Edit: these also work as expected, but it’s inconsistent since they should be equivalent to the first example:

    std.debug.print("before: {any}\n", .{e.cmd.count});
    e.cmd.count = .{ .second = e.cmd.count.first };
    std.debug.print("after: {any}\n", .{e.cmd.count});
    std.debug.print("before: {any}\n", .{e.cmd.count});
    e.cmd.count = .{ .second = e.cmd.count.first, .first = 0 };
    std.debug.print("after: {any}\n", .{e.cmd.count});
before: .{ .first = 3, .second = 0 }
after: .{ .first = 0, .second = 3 }
1 Like

Agreed this is midly annoying.

This is as far as I know working as intended. See this section of the language reference.

3 Likes

Definitely, thanks.

I’d even call it hidden control flow.

Relevant issues:

https://codeberg.org/ziglang/zig/issues/32009

1 Like