This is a lot harder than adding fields. I was playing around with this and most of the options aren’t great. You can easily add a comptime void
field to a struct and then check if you have it.
Essentially, Declaration
leaves you pretty much abandoned at this point:
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Declaration = struct {
name: [:0]const u8,
};
While StructField
gives you what you want:
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const StructField = struct {
name: [:0]const u8,
type: type,
default_value: ?*const anyopaque,
is_comptime: bool,
alignment: comptime_int,
};
And if you try to add declarations using @Type
then you’ll get this error:
main.zig:20:12: error: reified structs must have no decls
The thing is, I can add a comptime field to my struct through reification:
const S = struct {
x: usize = 42, // of course
};
pub fn MakeImportant(comptime T: type) type {
const fields = @typeInfo(T).Struct.fields;
comptime var new_fields: [fields.len + 1]std.builtin.Type.StructField = undefined;
for (fields, 0..) |field, i| {
new_fields[i] = field;
}
new_fields[fields.len] = .{
.name = "important",
.type = void,
.default_value = &void{},
.is_comptime = true,
.alignment = 0,
};
return @Type(.{ .Struct = .{
.layout = .auto,
.fields = new_fields[0..],
.decls = &.{},
.is_tuple = false,
.backing_integer = null,
} });
}
pub fn main() !void {
const s: MakeImportant(S) = .{};
std.debug.print("is important: {}", .{ @hasField(@TypeOf(s), "important")});
}
And in this case, the size of the struct is still 8 - the size of its only usize
member variable.