The issue here is that the stuff with Static.i does not work (and the LastT has the same issue), even though similiar with comptime var works, but the state can not be preserved between calls. And I can’t seem to be able to make any variation on Static.i work.
Is it impossible, or am I just missing something?
PS: I only really want to construct it this way because it is ZLS friendly. I think I should be able to construct my logger wrapper with @Struct but I think I would lose the ZLS autocompletion. So if you know of any zls friendly alternatives, please do let me know. The second best think I can think of is to change the API to
And compiler still says “captured value contains reference to comptime var”. No runtime involved. No comptime pointer being referenced from the created struct (or the factory function). I thought I could somehow manage with @src, but it can’t actually be used in struct declaration even if it is actually in a function. Non comptime var does not work either as it says the counter is not accessible, even though the context should always be comptime.
So I guess I am out of luck, and I will have to manually manage this. At least until there is LSP that undestands types created with @Struct. Which is unfortunate, because this feels like it should have been easy…
Is there really no way at all to find from within the namedLog what it is being assigned to? Any way at all (without manually providing the information).
declarations are evaluated in order of when they are seen used during analysis, so this wouldnt work even if you could have mutable comptime global state.
That is pretty good insight though, now it kinda makes sense why it is not possible to do it that way. Any clue why I can’t use @src in that function creating a structure? That would have probably allowed me to parse the name that is being assigned to.
I feel like the last example can be hardly considered global comptime state… It certainly feels pretty well contained. When I thought of that I thought it would work for sure… it still feels counterintuitive that the same thing that would likely be trivial with @Struct can’t really be expressed in this more verbose way. Oh well…
Fair, didn’t realize that. Never actually used it and always thought it points to where the @src was called. So there is no way at all to be able to determine what name the value is being assigned to, without actually providing some information manually.
Actually the @srcdoes point to the place where it was called. Multiple @src in the same function do give different results. So if the @src was usable there, it would allow me to determine what it is being assigned to.
Well, I thought the file field it returns is actually the file content so that I would be able to parse the decl name. Now that I am looking at it its just file name. Still, I would have probably been able to do something like
So I ended up duplicating the decl name into the function factory and adding a comptime test for that. The comptime test was very tricky to get right, took me maybe 2 hours, because there is some weirdness in how strings are compared in comptime and so the newly created function in the test was different from the function created outside of the test. The solution was to do this in the factory function: instead of using provided name directly, find the decl with that name from @This(), and use the decl.name. If I had gone the index based way I wouldn’t have to deal with that gotcha but there are issues with index based that I was unhappy with.
fn testLogger(This: type) void {
comptime {
const info = @typeInfo(This).@"struct";
for (info.decls[1..]) |decl| {
if (@field(This, decl.name) != namedLogStr(This, decl.name)) {
@compileError(This.name ++ "." ++ decl.name ++ " has incorrectly specified id. Must be ." ++ decl.name);
}
}
}
}
const Idk = struct {
logger: *Logger,
pub const name = "idk";
pub const streamingBody = namedLog(@This(), .streamingBody);
pub const streamingBody2 = namedLog(@This(), .streamingBody); // error: idk.streamingBody2 has incorrectly specified id. Must be .streamingBody2
comptime {
testLogger(@This());
}
};