the type of f above is not a function pointer type but only a bare function type. You need to place a * before the type. Note that because fonction pointers point to constant data, you also need to place a const.
You already got your answer:
Function-body types can only be used at comptime.
But your original example tried to use them at run-time.
Function-body types are essentially only an identity that represents some function at compile time, once these functions get compiled into a program you can convert that identity to the corresponding pointer to the code of that function (wherever the compiler decides to put it) with the & address operator.
It is a struct field, function fields don’t exist.
The original example doesn’t use the field of function type at run-time.
But maybe you are right, it can be potentially used at run-time, at least from the semantic level. That is why the field needs an explicit comptime annotation.
Yes, you should be able to use the original Foo struct in a comptime var, but aren’t allowed to use it in a normal var, because then you could change the .f field at runtime which is impossible because values of its type don’t exist at runtime.
You can access them via instance.field_name, with const declarations you can only use Type.const_declaration, I think the former can be potentially useful in some situations where some code uses comptime ducktyping and always expects a specific field to be there and then you have a type where that field needs to be there, if it can’t ever be anything different. In that case using a comptime field allows you to keep the same ducktyping interface without needing to have runtime mutable data for the field.
That said, I am not sure whether this gets frequently used anywhere.
You can create Foo instances if those are used/mutated at comptime, if you also want to change them at runtime you need to use function pointers instead, so that the Foo-instance can exist at runtime.
Because = in a struct field does not set a value at compile time.
It sets the default value when the structure is constructed and this happens at runtime.
e.g.
y: u8 = 123,
Does not mean set 123 to y. y can get any u8 value. 123 is the initial value if y is not specified in the struct construction.
I think that would be awkward for a compiled language that evaluates most code eagerly, because it would add a ton of possible combinations for how the code could be run / compiled, when specific parameters are comptime known in one place, but runtime known in another you would end up with different concrete types that aren’t compatible.
Also you would completely lose the clear separation between comptime var and var. I just don’t think this fits the language, it would be to implicit and messy (if you try to avoid fully redesigning the language towards allowing partial comptime evaluation everywhere, which probably would make it a very different language).
I think having partial evaluation as a general concept in a compiled language is a thing you would start building your language with, not something that you tack on later.
So “why can’t I just” seems like too much magical thinking here, you can’t just add a feature, it needs to fit and I don’t know how you would fit this into Zig, without a lot of other things breaking.
But because this is explain and not brainstorming, we also can just say:
no there are no partially comptime evaluated struct values, you either evaluate at comptime or runtime, not half comptime and half runtime
Instead you can put the comptime parts in a struct that is used at comptime
and then when you are done doing comptime things copy the values into a runtime struct that may have more other fields beyond those comptime ones.
The benefit of that is that it makes it clear what happens at comptime and what at runtime.
The answer is simple comptime fields are constant and have the value they are declared with, that is simply how it is.
You can ask why, but the answer is, because Zig implemented it that way.
I think the compiler gives the best explanation:
comptimefields.zig:28:14: error: variable of type 'comptimefields.Bar' must be const or comptime
var bar: Bar = .{};
^~~
comptimefields.zig:7:8: note: struct requires comptime because of this field
f: fn () void = dummy,
^~~~~~~~~~
comptimefields.zig:7:8: note: use '*const fn () void' for a function pointer type
What I want to change are the non-comptime and non-const fields of a struct which contains non-comptime function/type fields, not the function/type fields.