Skip to content
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

struct with field default initialized to size of the struct gives false positive 'depends on itself' error #12029

Closed
Tracked by #89
andrewrk opened this issue Jul 7, 2022 · 3 comments · Fixed by #12096
Assignees
Labels
bug Observed behavior contradicts documented or intended behavior frontend Tokenization, parsing, AstGen, Sema, and Liveness.
Milestone

Comments

@andrewrk
Copy link
Member

andrewrk commented Jul 7, 2022

Zig Version: 0.10.0-dev.2857+4e002dde6

const S = extern struct {
    size: u8 = @sizeOf(S),
    blah: u16,
};

test "struct default value initialize to size of itself" {
    var s: S = undefined;
    _ = s;
}
[nix-shell:~/dev/zig/build-release]$ stage2/bin/zig test test3.zig 
test3.zig:8:5: error: struct 'test3.S' depends on itself
    size: u8 = @sizeOf(S),
    ^
@andrewrk andrewrk added bug Observed behavior contradicts documented or intended behavior os-macos frontend Tokenization, parsing, AstGen, Sema, and Liveness. labels Jul 7, 2022
@andrewrk andrewrk added this to the 0.10.0 milestone Jul 7, 2022
@endel
Copy link
Contributor

endel commented Jul 7, 2022

I don't mean to generate noise, perhaps this report can collaborate to finding out a related problem:


I've tried to use io_mode = .evented on @Luukdegram's feilich example server, and also got "depends on itself" errors.

Without io_mode set no compiler errors appear.

./src/encryption.zig:139:13: error: '@Frame(.feilich.encryption.EncryptedReadWriter(std.io.reader.Reader(std.net.Stream,std.os.ReadError,std.net.Stream.read),std.io.writer.Writer(std.net.Stream,std.os.WriteError,std.net.Stream.write)).read)' depends on itself
        pub fn read(self: *Self, buf: []u8) ReadError!usize {
            ^
./src/encryption.zig:150:41: note: when analyzing type '@Frame(.feilich.encryption.EncryptedReadWriter(std.io.reader.Reader(std.net.Stream,std.os.ReadError,std.net.Stream.read),std.io.writer.Writer(std.net.Stream,std.os.WriteError,std.net.Stream.write)).read)' here
                        return self.read(buf);
                                        ^
/Users/endel/Projects/zig/zig/zig-dev/lib/zig/std/io/reader.zig:26:26: note: while checking if 'std.io.reader.Reader(*.feilich.encryption.EncryptedReadWriter(std.io.reader.Reader(std.net.Stream,std.os.ReadError,std.net.Stream.read),std.io.writer.Writer(std.net.Stream,std.os.WriteError,std.net.Stream.write)),.feilich.encryption.EncryptedReadWriter(std.io.reader.Reader(std.net.Stream,std.os.ReadError,std.net.Stream.read),std.io.writer.Writer(std.net.Stream,std.os.WriteError,std.net.Stream.write)).ReadError,.feilich.encryption.EncryptedReadWriter(std.io.reader.Reader(std.net.Stream,std.os.ReadError,std.net.Stream.read),std.io.writer.Writer(std.net.Stream,std.os.WriteError,std.net.Stream.write)).read).read' is async
            return readFn(self.context, buffer);
                         ^
./src/Server.zig:272:46: note: when analyzing type '@Frame(.feilich.Server.connect)' here
    var read_len = try decryption_reader.read(&decrypted_data);
                                             ^
./examples/server.zig:18:27: note: when analyzing type '@Frame(main)' here
        tls_server.connect(stream.reader(), stream.writer()) catch |err| {
                          ^
/Users/endel/Projects/zig/zig/zig-dev/lib/zig/std/start.zig:581:37: note: while checking if 'std.start.callMain' is async
            const result = root.main() catch |err| {
                                    ^
server...The following command exited with error code 1:

(MacOS, arm64)

@andrewrk andrewrk mentioned this issue Jul 11, 2022
5 tasks
@andrewrk
Copy link
Member Author

Thanks for the data point. This issue is for stage2 while I believe your example is using stage1.

@andrewrk andrewrk removed the os-macos label Jul 12, 2022
@andrewrk andrewrk changed the title false positive 'depends on itself' compile errors when building std lib tests for macos struct with field default initialized to size of the struct gives false positive 'depends on itself' error Jul 12, 2022
@andrewrk
Copy link
Member Author

andrewrk commented Jul 12, 2022

Problem

The field types and default values are generated as part of the same expression, which are then referenced later:

    %21 = extended(struct_decl(parent, Extern, {}, {
      %22 = decl_val("U8") token_offset:8:11
      %23 = decl_val("S") token_offset:8:24
      %24 = size_of(%23) node_offset:8:16
      %25 = as_node(%22, %24) node_offset:8:16
      %26 = decl_val("U16") token_offset:9:11
      %27 = break_inline(%21, @Zir.Inst.Ref.void_value)
    }, {
      size: %22 = %25,
      blah: %26,
    }) node_offset:7:18

Solution

Break this into two: one for the types; one for the values. The types go first, then the values. Something like this:

    %21 = extended(struct_decl(parent, Extern, {}, {
      %22 = decl_val("U8") token_offset:8:11
      %23 = decl_val("S") token_offset:8:24
      %26 = decl_val("U16") token_offset:9:11
      %27 = break_inline(%21, @Zir.Inst.Ref.void_value)
    }, {
      %24 = size_of(%23) node_offset:8:16
      %25 = as_node(%22, %24) node_offset:8:16
      %a = break_inline(%21, @Zir.Inst.Ref.void_value)
    }, {
      size: %22 = %25,
      blah: %26,
    }) node_offset:7:18

Alternate Solution

Do the coercion to the field type later:

      %25 = as_node(%22, %24) node_offset:8:16

If this part is omitted from the ZIR for the field initialization then everything works fine due to the lazy_sizeof Value Tag.

Edit: I think the main solution idea is better than the Alternate Solution because it handles more cases and is generally more straightforward.

@andrewrk andrewrk self-assigned this Jul 13, 2022
andrewrk added a commit that referenced this issue Jul 13, 2022
Previously, struct types, alignment values, and initialization
expressions were all lowered into the same ZIR body, which caused false
positive "depends on itself" errors when the initialization expression
depended on the size of the struct.

This also uses ResultLoc.coerced_ty for struct field alignment and
initialization values. The resulting ZIR encoding ends up being roughly
the same, neither smaller nor larger than previously.

Closes #12029
andrewrk added a commit that referenced this issue Jul 13, 2022
Previously, struct types, alignment values, and initialization
expressions were all lowered into the same ZIR body, which caused false
positive "depends on itself" errors when the initialization expression
depended on the size of the struct.

This also uses ResultLoc.coerced_ty for struct field alignment and
initialization values. The resulting ZIR encoding ends up being roughly
the same, neither smaller nor larger than previously.

Closes #12029
vrischmann pushed a commit to vrischmann/zig that referenced this issue Jul 13, 2022
Previously, struct types, alignment values, and initialization
expressions were all lowered into the same ZIR body, which caused false
positive "depends on itself" errors when the initialization expression
depended on the size of the struct.

This also uses ResultLoc.coerced_ty for struct field alignment and
initialization values. The resulting ZIR encoding ends up being roughly
the same, neither smaller nor larger than previously.

Closes ziglang#12029
andrewrk added a commit that referenced this issue Jul 19, 2022
Previously, struct types, alignment values, and initialization
expressions were all lowered into the same ZIR body, which caused false
positive "depends on itself" errors when the initialization expression
depended on the size of the struct.

This also uses ResultLoc.coerced_ty for struct field alignment and
initialization values. The resulting ZIR encoding ends up being roughly
the same, neither smaller nor larger than previously.

Closes #12029
wooster0 pushed a commit to wooster0/zig that referenced this issue Jul 24, 2022
Previously, struct types, alignment values, and initialization
expressions were all lowered into the same ZIR body, which caused false
positive "depends on itself" errors when the initialization expression
depended on the size of the struct.

This also uses ResultLoc.coerced_ty for struct field alignment and
initialization values. The resulting ZIR encoding ends up being roughly
the same, neither smaller nor larger than previously.

Closes ziglang#12029
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 frontend Tokenization, parsing, AstGen, Sema, and Liveness.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants