Skip to content

Stage 1 ir_analyze_container_member_access_inner panic #9142

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
AnneKitsune opened this issue Jun 17, 2021 · 6 comments
Closed

Stage 1 ir_analyze_container_member_access_inner panic #9142

AnneKitsune opened this issue Jun 17, 2021 · 6 comments
Labels
bug Observed behavior contradicts documented or intended behavior stage1 The process of building from source via WebAssembly and the C backend.
Milestone

Comments

@AnneKitsune
Copy link

Reproduction:

const Dispatcher = struct {
    systems: anytype,
    fn doSomething(comptime this: *const @This()) void {
        for (this.systems) |sys| {
        }
    }
};

pub fn main() anyerror!void {
    // init separately, because if we do it inside of the struct
    // init it will show an unclear error (#9141)
    const systems = .{5, 6};
    const dispatcher = Dispatcher {
        .systems = systems,
    };
    dispatcher.doSomething();
}

Error:

zig run src/main.zig
Assertion failed at /home/jojolepro/.cache/yay/zig-git/src/zig/src/stage1/ir.cpp:14690 in ir_analyze_container_member_access_inner. This is a bug in the Zig compiler.thread 48199 panic:
Unable to dump stack trace: debug info stripped
zsh: abort (core dumped)  zig run src/main.zig

I get the same output using zig run -O Debug src/main.zig.

Expected: Probably an error, but I'm not sure what the exact behavior should be here.

Version:
0.9.0-dev.187+bfe3558ef

@Vexu Vexu added bug Observed behavior contradicts documented or intended behavior stage1 The process of building from source via WebAssembly and the C backend. labels Jun 18, 2021
@Vexu Vexu added this to the 0.10.0 milestone Jun 18, 2021
@AnneKitsune
Copy link
Author

I learned a bit more of the language and I think the issue is that anytype is allowed in the struct fields when it shouldn't be. Is this correct @Vexu ?

@Vexu
Copy link
Member

Vexu commented Jul 1, 2021

I don't see any reason for the anytype field not to be allowed here, the stage1 implementation is just buggy.

@UgiNyaa
Copy link

UgiNyaa commented Sep 6, 2021

A reason for not allowing anytype in structs could be because of its ambiguity. Take the following example:

const std = @import("std");

const Dispatcher = struct {
    systems: anytype,
    fn doSomething(comptime this: *const @This()) void {
        for (this.systems) |sys| {
        }
    }
};

test {
    const systems1 = .{5, 6};
    const dispatcher1 = Dispatcher {
        .systems = systems1,
    };
    const systems2 = 5;
    const dispatcher2 = Dispatcher {
        .systems = systems2,
    };

    try std.testing.expect(@TypeOf(dispatcher1) != @TypeOf(dispatcher2));
}

Would you expect this to fail or to succeed? I would expect this to succeed and that the types of dispatcher1 and dispatcher2 are not equal, since they would have different sizes. In the current implementation (version 0.8.0), this test fails.

Another example:

test {
    const systems1 = .{5, 6};
    const dispatcher1 = Dispatcher {
        .systems = systems1,
    };
    const systems2 = 5;
    const dispatcher2 = Dispatcher {
        .systems = systems2,
    };

    try std.testing.expect(@TypeOf(dispatcher1) != Dispatcher);
    try std.testing.expect(@TypeOf(dispatcher2) != Dispatcher);
}

Would you expect this to fail or to succeed? This question is a lot more though, since dispatcher1 and dispatcher2 were created with the same Dispatcher type, but they have different sizes. I am unsure but I think I would expect this test to succeed (partially because I expected the last test to succeed, and transitivity is a defining feature for equality). In the current implementation (version 0.8.0), this test fails.

Alternative

I think the right way to do something like this is to use generics:

fn Dispatcher(comptime T: type) type {
    return struct {
        systems: T,
        fn doSomething(comptime this: *const @This()) void {
            inline for (this.systems) |sys| {
            }
        }
    };
}

test {
    const systems = .{5, 6};
    const dispatcher = Dispatcher(@TypeOf(systems)) {
        .systems = systems,
    };

    dispatcher.doSomething();
}

NOTE: I added inline before the for loop, because it is dealing with a tuple. See https://ziglang.org/documentation/0.8.0/#Anonymous-Struct-Literals

This removes the problem of the Dispatcher being a type with an unknown size. Rather, its a function returning a type with a known size.

@saltzm
Copy link

saltzm commented Feb 16, 2022

I ran into this as well. In my case I had a function with an anytype parameter and some other parameters that I wanted to refactor to group into a struct.

Link to the crashing case in godbolt

Link with some workarounds using a function returning a type

@AnneKitsune
Copy link
Author

Zig master returns a proper error:

/tmp/hen/src/main.zig:7:58: error: expected type expression, found 'anytype'
fn fooWithStructArgs(comptime request: struct { printer: anytype, i: u32, j: u32}) void {

Closing the issue :)

@nektro
Copy link
Contributor

nektro commented Apr 20, 2022

yeah anytype fields were removed from Zig in #10766

@Vexu Vexu modified the milestones: 0.12.0, 0.10.0 Apr 23, 2022
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

5 participants