No, it does not work, I added the init if it could change something but it didnt.
And that observer probably will be deleted because is no longer used, the one it is gonna stay is the one from scopeGlobal.zig.
Your imports are forming big olā loopy circles. Thatās allowed in Zig, but itās not a great idea to be this devoted to the practice, and this is why.
Somehow youāre forcing semantic analysis to know something about a type, before itās possible for the type to exist. That might be due to a limitation in current-year comptime evaluation, or it might be that what youāre expressing is literally an impossible type of self-reference, I canāt tell.
Iād suggest that you go through and break as many of those cycles as you can. Itās likely that one of those will fix the problem.
Some time ago I tried to see how zig project are divided and how do I make imports.
That is why I try to join them in the mod.zig,
Is there a place I could use as reference?
What Iām suggesting is more specific than that. Somehow, your cyclic import system has introduced a circular dependency, type construction cannot continue because it relies on a type which cannot exist at the time semantic analysis needs it to.
You have a lot of cyclic imports, and not just short cycles either. Just get rid of as many of those as you can, and youāll either fix the problem, or find it by the process of elimination.
Current comptime semantic analysis will have more such problems than is strictly required, Zig is a work in progress. But itās also possible to write out types which are logically impossible, and I canāt tell which situation your code is in right now because the dependency graph is all over the place.
Could you please post the error youāre getting, with full reference trace? I tried looking and Iām not understanding which two lines youāre talking about.
You could experiment with type erasing some of the pointers, to break the cycle.
It also might be possible to change some code to not depend on some type and thus break the cycle. (For example I had a case where I only needed the size of the type not the entire type, so through calculating the needed size in another (more manual) way, I could avoid the dependency on the type which caused the cycle, so avoid dependencies on full types when you really just need that type to calculate something)
I think type erasure is a pretty good tool to avoid creating too crazy type-dependency cycles, then you could possible separate your implementation into parts that are type erased and other parts which arenāt but make use of the former.
Also instead of each thing being given a bunch of types and calculating other derived types from that you may have to create a single type-family-function that gets all the input types and then calculates the correct types step by step, when writing things like this it becomes pretty obvious when you have some impossible cycle somewhere and also whether there is some trick to break it (like the case where just the size needed to match).
Another tip would be to choose when and what has to be typed vs can be untyped, for example you could have some pointers type erased and then write a function that is given the actual type as a parameter, thus the type only needs to be known by the callsite of that function. (This is one way you could get rid of some of the dependencies)
Why do you say āshould beā here? Because Iām pretty sure this original solution is why thereās no dependency loop. in ObserverParams = std.meta.Tuple(&.{ TranslationUnit, Allocator, Parser.NodeIndex, ?*Report.Reports }); the tuple .{ TranslationUnit, Allocator, Parser.NodeIndex, ?*Report.Reports } exists before ObserverParams, and itās pointer is location is passed into std.meta. Thus; because itās already resolved, prior to trying to resolve ObserverParams, the compiler doesnāt need to look them up to resolve ObserverParams. I thinkā¦
I only moderately confident about this⦠so either way, @EvilAlliance the zig way to solve this is make these types, an argument that generates a type for you. Expression.zig would become a function, and take any set of params. Then you donāt need to call
at all, because every call carries that information with it. The compiler will resolve it for you, and you donāt have to worry about missing it because the type system will prevent you from passing the wrong, or incompatible type.
Instead of making the Translation Unit a pointer, and have to allocate in the heap each time I prefer making the observer params in the scope a opaque pointer, the type safety is a little lost, but is a little less than the other.
And yes the problem there was translation unti, I think that the bug mentioned is the cause because to have the size of the VTable it is not needed to know the size of a parameter
Update: I fount a way to keep the Type Safety, I can make the argument of the method the observer params, but the rest as *anyopaque