Can't create slices at comptime any more?

Today I downloaded the latest version of master. I notice that the following code is now failing:

fn ArgumentStruct(comptime function: anytype) type {
    const info = @typeInfo(@TypeOf(function)).Fn;
    var fields: [info.params.len + 1]std.builtin.Type.StructField = undefined;
    var count = 0;
    for (info.params) |param| {
        if (param.type != std.mem.Allocator) {
            const name = std.fmt.comptimePrint("{d}", .{count});
            fields[count] = .{
                .name = name,
                .type = param.type orelse void,
                .is_comptime = false,
                .alignment = @alignOf(param.type orelse void),
                .default_value = null,
            };
            count += 1;
        }
    }
    fields[count] = .{
        .name = "retval",
        .type = info.return_type orelse void,
        .is_comptime = false,
        .alignment = @alignOf(info.return_type orelse void),
        .default_value = null,
    };
    count += 1;
    return @Type(.{
        .Struct = .{
            .layout = Auto,
            .decls = &.{},
            .fields = fields[0..count],
            .is_tuple = false,
        },
    });
}

test "ArgumentStruct" {
    const Test = struct {
        fn A(a: i32, b: bool) bool {
            return if (a > 10 and b) true else false;
        }

        fn B(s: []const u8) void {
            _ = s;
        }

        fn C(alloc: std.mem.Allocator, arg1: i32, arg2: i32) bool {
            _ = alloc;
            return arg1 < arg2;
        }
    };
    const ArgA = ArgumentStruct(Test.A);
    const fieldsA = std.meta.fields(ArgA);
    assert(fieldsA.len == 3);
    assert(fieldsA[0].name[0] == '0');
    assert(fieldsA[1].name[0] == '1');
    assert(fieldsA[2].name[0] == 'r');
    const ArgB = ArgumentStruct(Test.B);
    const fieldsB = std.meta.fields(ArgB);
    assert(fieldsB.len == 2);
    assert(fieldsB[0].name[0] == '0');
    assert(fieldsB[1].name[0] == 'r');
    const ArgC = ArgumentStruct(Test.C);
    const fieldsC = std.meta.fields(ArgC);
    assert(fieldsC.len == 3);
}
exporter.zig:1688:19: error: comptime dereference requires '[3]builtin.Type.StructField' to have a well-defined layout, but it does not.
    return @Type(.{
                 ~^
exporter.zig:1724:32: note: called from here
    const ArgC = ArgumentStruct(Test.C);
                 ~~~~~~~~~~~~~~^~~~~~~~

The function is failing for function C because field[0..count] would actually create a slice. I managed to work around the issue already, but I’m wondering whether this is how Zig is going to work from now on or a regression that will get fixed.

hello ;
there is a big explanation on the last master

When called with C, fields array length is 4 (info.params.len + 1) because it includes the first parameter. But only 3 fields are initialized.
My guess is that this is a regression related to passing a slice and not the entire array.

2 Likes

This is #19452 – sorry for the bug!

4 Likes