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.
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;
};
}