Search code examples
zig

Error when generating struct field names using Zig comptime


I am trying to write a Zig program that uses comptime to generate field names of a struct, but I encounter an error when building the project.

Zig version: 0.13.0

Below is my code:

const std = @import("std");

var person_field_names = generateFieldNames(Person);

fn generateFieldNames(comptime T: type) []const []const u8 {
    comptime {
        const typeInfo = @typeInfo(T);
        switch (typeInfo) {
            .Struct => |structInfo| {
                const field_count = structInfo.fields.len;
                var field_names: [field_count][]const u8 = undefined;

                var i: usize = 0;
                while (i < field_count) : (i += 1) {
                    const field = structInfo.fields[i];
                    field_names[i] = field.name;
                }
                return &field_names;
            },
            else => @compileError("Only structs are supported!"),
        }
    }
}

const Person = struct {
    name: []const u8,
    age: u8,
};

pub fn main() void {
    for (person_field_names) |name| {
        std.debug.print("Field name: {s}\n", .{name});
    }
}

When I run zig build run, I get the following error:

$ zig build run
run
└─ run comptime_test
   └─ zig build-exe comptime_test Debug native failure
error: the following command exited with error code 3:
C:\softs\zig\zig.exe build-exe -ODebug -Mroot=C:\workspace\zig\comptime_test\src\main.zig --cache-dir C:\workspace\zig\comptime_test\zig-cache --global-cache-dir C:\Users\myhfs\AppData\Local\zig --name comptime_test --listen=-
Build Summary: 0/5 steps succeeded; 1 failed (disable with --summary none)
run transitive failure
└─ run comptime_test transitive failure
   ├─ zig build-exe comptime_test Debug native failure
   └─ install transitive failure
      └─ install comptime_test transitive failure
         └─ zig build-exe comptime_test Debug native (reused)
error: the following build command failed with exit code 1:
C:\workspace\zig\comptime_test\zig-cache\o\9c79a56d0821539e91985b5f4384125d\build.exe C:\softs\zig\zig.exe C:\workspace\zig\comptime_test C:\workspace\zig\comptime_test\zig-cache C:\Users\myhfs\AppData\Local\zig --seed 0xcf452477 -Z3cc02acbdb7abbe2 run

What is causing this error, and how can I fix it?

The error code seems related to how I am handling the array of field names. I believe the issue is with the comptime handling or returning the field names from the function.


Solution

  • The standard library has a function that does what you're trying to do: std.meta.fieldNames.

    I've managed to get your code to work by replacing

    return &field_names;
    

    with

    const final = field_names;
    return &final;
    

    A trick I've seen in the std.meta.fieldNames. Here's its current source code (Zig 0.13.0) for reference:

    pub fn fieldNames(comptime T: type) *const [fields(T).len][:0]const u8 {
        return comptime blk: {
            const fieldInfos = fields(T);
            var names: [fieldInfos.len][:0]const u8 = undefined;
            // This concat can be removed with the next zig1 update.
            for (&names, fieldInfos) |*name, field| name.* = field.name ++ "";
            const final = names;
            break :blk &final;
        };
    }