Skip to content

comptime: declaring a struct in an 'inline for' fails to compile #4148

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
xxxbxxx opened this issue Jan 11, 2020 · 7 comments
Closed

comptime: declaring a struct in an 'inline for' fails to compile #4148

xxxbxxx opened this issue Jan 11, 2020 · 7 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

@xxxbxxx
Copy link
Contributor

xxxbxxx commented Jan 11, 2020

hi.

This fails to compile:

export fn func() void {
    inline for ([_]u8{1,2}) |phase| {
        const S = struct {
            val: if (phase == 1) u32 else [2]f32,
        };
        const s = S{.val = if (phase== 1) 1 else [2]f32{1,2} };
    }
}

(with error: 6:57: error: array access of non-array type 'u32')

Looks like the second iteration tries to use the struct from the first iteration or something like this.

If I declare both structs before hand, it works:

export fn func2() void {
    const S1 = struct {
        val: u32,
    };
    const S2 = struct {
        val: [2]f32,
    };
    inline for ([_]u8{1,2}) |phase| {
        const S = if (phase == 1) S1 else S2;
        const s = S{.val = if (phase== 1) 1 else [2]f32{1,2} };
    }
}
@andrewrk andrewrk added this to the 0.7.0 milestone Jan 26, 2020
@andrewrk andrewrk added bug Observed behavior contradicts documented or intended behavior stage1 The process of building from source via WebAssembly and the C backend. labels Jan 26, 2020
@Rocknest
Copy link
Contributor

Anon list literal cannot coerce into a type if the type is provided explicitly.

export fn entry() void {
    const T = struct {c: usize, d: usize};
    var x: T = T { .c = 546343, .d = 7};
    var z: struct {a: usize, b: usize} = .{x.c, x.d};
}

Compile error is nonsense and misleading.

source.zig:4:45: error: array access of non-array type 'struct:4:12'
    var z: struct {a: usize, b: usize} = .{x.c, x.d};
                                            ^

@Rocknest
Copy link
Contributor

When using intermediate generic function this code actually works:

export fn func() void {
    inline for ([_]u8{1,2}) |phase| {
        const S = MakeStruct(if (phase == 1) u32 else [2]f32);
        const s = S{.val = if (phase== 1) 1 else [2]f32{1,2} };
    }
}

fn MakeStruct(comptime ArgType: type) type {
    return struct {
        val: ArgType,
    };
}}

@LemonBoy
Copy link
Contributor

Compile error is nonsense and misleading.

The compiler error is correct and on point. The expression .{x.c, x.d} is valid as initializer for array types and the compiler desugars it as:

lhs[0] = x.c;
lhs[1] = x.d;

If lhs is a struct, like it is in your case, you get an error because of that.

The correct way to do what you wanted to do is:

var z: struct {a: usize, b: usize} = .{.a = x.c, .b = x.d};

@Rocknest
Copy link
Contributor

@LemonBoy Why not allow this coercion? By default it will be struct anyway:

export fn entry() void {
    const T = struct {c: usize, d: usize};
    var x: T = T { .c = 546343, .d = 7};
    var z = .{x.c, x.d};
    // @TypeOf(z) is struct {@"0": usize, @"1": usize}
    var z2: @TypeOf(z) = .{.@"0" = x.c, .@"1" = x.d};
}

Anyway the error should be more clear e.g. "use struct literal instead"

Related #4335

@LemonBoy
Copy link
Contributor

LemonBoy commented Jan 31, 2020

Why not allow this coercion?

Because it's a time-bomb, if you swap the order of two entries in a struct definition the initializer will still work but your code will blow up unexpectedly.

Edit: and for non-extern, non-packed struct the field order is unspecified.

Anyway the error should be more clear e.g. "use struct literal instead"

Aye, there's already a initializing array with struct syntax error but not the other way around.

@Rocknest
Copy link
Contributor

Because it's a time-bomb

Same can be said about functions - they are all time-bombs - if you swap order of parameters and the types match then the code will compile but may 'blow up'

Edit: and for non-extern, non-packed struct the field order is unspecified.

Order of fields in memory? How is that related?

@xxxbxxx
Copy link
Contributor Author

xxxbxxx commented Oct 8, 2022

fixed in stage2

@xxxbxxx xxxbxxx closed this as completed Oct 8, 2022
@andrewrk andrewrk modified the milestones: 0.12.0, 0.10.0 Oct 12, 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

4 participants