Is this supposed to work? I know there were a lot of changes to type resolution recently, so I figured I would try this again. It didn’t work before and it still doesn’t work. Its very similar to std.builtin.Type.StructField. Should it work?
Sorry I can’t answer your question but for my own education, why not use a comptime parameter in that particular case? Maybe you have a more complicated use case where this it not possible.
You want the type for default_value to change depending on the future value of another field on and per instantiation.
It wouldn’t ever work with the syntax you used, and I don’t know why zig would ever support this. What utility does it have that a type returning function couldn’t fulfil.
You’re trying to access a field as if it was a declaration.
What you’re doing is equivalent to having a Foo = struct { bar: i32 } and then attempting to access Foo.bar it’s nonsensical. You’ve just obfuscated it by using @This, @TypeOf and by placing the access within the definition of the struct.
Also consider this: what should @sizeOf(Argument) be?
A field type is not allowed to depend on the value of another field, and it’s extremely unlikely that this ever changes. You used to be able to sorta do this with something called “anytype fields”, but they were removed when we transitioned to the self-hosted compiler back in 0.10.0, I believe because they were a pretty janky language feature with insufficient use cases to justify their complexity.
That’s why std.builtin.Type.StructField does what it does with an anyopaque pointer. If you need this functionality in your own code, I recommend copying its approach. Of course, you can use an initializer function to avoid the slight awkwardness of initializing that pointer. I’m sure you can figure out what that’d look like, but for completeness, here’s how you could write something like your original example:
pub const Argument = struct {
name: [:0]const u8,
Type: type,
/// Must be a valid `*const Type`. See `defaultValue` for a convenient accessor.
default_value_ptr: *const anyopaque,
/// `inline` to ensure return value is comptime-known.
pub inline fn defaultValue(comptime a: Argument) a.Type {
const ptr: *const a.Type = @ptrCast(@alignCast(a.default_value_ptr));
return ptr.*;
}
pub fn init(
comptime name: [:0]const u8,
comptime Type: type,
comptime default_value: Type,
) Argument {
return .{
.name = name,
.Type = Type,
.default_value_ptr = &default_value,
};
}
};