Skip to content

Uninitialized struct values in tuples which also contain runtime (var) values #11662

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
tim-barry opened this issue May 17, 2022 · 1 comment
Closed
Labels
bug Observed behavior contradicts documented or intended behavior stage1 The process of building from source via WebAssembly and the C backend.
Milestone

Comments

@tim-barry
Copy link

Zig Version

0.10.0-dev.2224+5b03d55c5

Steps to Reproduce

Some struct values directly declared/created in tuples are not correctly initialized when the tuple also contains a runtime/var value. Example of a value that is not initialized is 1002 in the following code snippet: const S = struct {i: i32}; var v = S{ .i = 1001}; std.debug.print("{} {}\n", .{v, S{.i = 1002}});. Instead of printing something like "S{.i = 1001} S{.i = 1002}", it prints something like "S{.i = 1001} S{.i = 0}" or "S{.i = 1001} S{.i = 1535116088}". I originally came across this issue on 0.9.0 while learning string formatting, writing a program for 99 bottles of beer on the wall. Initially I thought it was an issue with print/format, but I found that it also happened in tuples without using print/format. I am on windows, but I believe this also happens on linux as I was able to see the bug on godbolt (zig version 0.9.0).

I searched the issue tracker and found a few tuple-related bugs, of the ones I found I think #7878 is probably the most similar or potentially related. Seems like it is also potentially related to result location semantics, which I do not really understand much about.

A full program that tests some different tuples:

const std = @import("std");
const expect = std.testing.expect;
const S = struct { i: i32 };

fn expectCorrect(tuple: anytype) !void {
    try expect(tuple[0].i == 1001);
    try expect(tuple[1].i == 1002);
    try expect(tuple[2].i == 1003);
}

pub fn main() !void {
    var v1001: S = .{ .i = 1001 };
    var v1002: S = .{ .i = 1002 };
    const c1002: S = .{ .i = 1002 };
    // First three work as expected
    try expectCorrect(.{ S{ .i = 1001 }, S{ .i = 1002 }, S{ .i = 1003 } }); // All comptime-known/const (?)
    try expectCorrect(.{ S{ .i = 1001 }, c1002, S{ .i = 1003 } });  // All comptime-known/const (?)
    try expectCorrect(.{ v1001, c1002, comptime S{ .i = 1003 } }); // the struct is explicitly marked comptime
    // neither S in the following line gets initialized
    const bad_tuple = .{ S{ .i = 1001 }, v1002, S{ .i = 1003 } };
    std.debug.print("Uninitialized values: {} {} {}\n", bad_tuple);
    try expectCorrect(bad_tuple);
    // also fails if it is not stored in a const variable but used directly
    try expectCorrect(.{ v1001, c1002, S{ .i = 1003 } });
}

For me this compiles and outputs:

$ zig.exe run uninit-bug.zig
Uninitialized values: S{ .i = 0 } S{ .i = 1002 } S{ .i = -194575560 }
error: TestUnexpectedResult
C:\...\zig-windows-x86_64-0.10.0-dev.2224+5b03d55c5\lib\std\testing.zig:347:14: 0x7ff7171e114b in td.testing.expect (uninit-bug.obj)
    if (!ok) return error.TestUnexpectedResult;
             ^
C:\...\Code\uninit-bug.zig:21:5: 0x7ff71720c79e in xpectCorrect (uninit-bug.obj)
    try expect(tuple[0].i == 1001);
    ^
C:\...\Code\uninit-bug.zig:37:5: 0x7ff7171e35bf in ain (uninit-bug.obj)
    try expectCorrect(bad_tuple);
    ^

Expected Behavior

I expected that the values would be correctly initialized as part of the tuple, and received by the functions expectCorrect and print. Or that I would receive some kind of compiler error for invalid code.

Actual Behavior

The compiler does not emit any error messages, but when the tuple contains a value declared as var and not const, the structs that are directly declared inside the tuple are not initialized (unless marked with comptime, or if you take a reference to them).

@tim-barry tim-barry added the bug Observed behavior contradicts documented or intended behavior label May 17, 2022
@Vexu Vexu added the stage1 The process of building from source via WebAssembly and the C backend. label Jun 1, 2022
@Vexu Vexu added this to the 0.12.0 milestone Jun 1, 2022
@Vexu
Copy link
Member

Vexu commented Jan 19, 2023

Fixed in self-hosted, tested in test/behavior/tuple.zig.

@Vexu Vexu closed this as completed Jan 19, 2023
@andrewrk andrewrk modified the milestones: 0.13.0, 0.11.0 Jan 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior stage1 The process of building from source via WebAssembly and the C backend.
Projects
None yet
Development

No branches or pull requests

3 participants