How to get more information for error "union depends on itself"

I am writing an interpreter with complex values and unions that contain various types and pointers.

While I can break the self dependency by using *anyopaque in a specific place that place isn’t ideal because it would require to cast from *anyopaque to a concrete type a lot. The error message just tells me that there is a self dependency, but not through which path of fields it is caused.

I was hoping to be able to specify something like -freference-trace and get more information about how that self dependency was found.

That way it would be easier to find other places where I could break the self-dependency.
So far I haven’t managed to create a minimal example and I am not completely sure under which conditions the error is actually triggered.

Is there some way to get the compiler to print more infos?


It might be related to this issue: Unnecessary "depends on itself" error with union tag enum · Issue #13760 · ziglang/zig · GitHub

But with the example given in that issue I get a detail message “While checking this field …”, my more complex example doesn’t show this, so maybe it is a bit different.


Now that I have removed a freelist data structure that used mixins to add extra methods the error has disappeared. It seems like it is some crazy combination of comptime, mixins, and multiple unions, where the compiler gives up and doesn’t print a lot of useful information anymore.

I think I will simply continue with using simpler and more concrete data structures, to avoid confusing the compiler by using too much comptime.

3 Likes

I’d still like to see the example though. I ran into something like that on a prior post and managed to get around it with anytype.

1 Like

I think you are right, it is probably possible to get around it with anytype at least thinking about it, it seems like it, however that seems like it shouldn’t be necessary when it isn’t necessary with more concrete types.

I think there is some implementation detail, about comptime where it treats pointers a bit to rigidly causing pointers to become a full dependency on the type, instead of treating it as a pointer of known size of a to be determined/resolved type. Seems like the type resolution isn’t lazy enough in some place. Or maybe it is a consequence of certain parts of comptime being more eager, then others? (This is just me speculating from what I have read and what it seems like, without having analyzed the implementation in depth or having thought about it deeply)

If I use anytype I loose the concreteness of available fields and methods, shown to me via zls. So that’s one reason for me to prefer to go with the more simple data structures.

Regarding showing the code I am a bit unsure, it is part of a passion project and I tend to have more fun with these, when I delay sharing it with anyone, until I got my desired learning, experimentation and fun out of it and until I am satisfied with its state.

Reducing it to a more minimal example would still be my preferred way of sharing an example for now, but with my last attempt at that, I just ended up with removing the more complex data structures. It is a bit time consuming to simplify the example when the compiler doesn’t print the field info and that makes me want to put a low-priority pin in it and put it on the bottom of my todo list :face_with_diagonal_mouth:

Another possibility might be the tool that @marler8997 recently mentioned to create minimal examples, but I don’t really know how that works, whether it applies here and how much effort that would be.

1 Like

You might be running into one of the bugs described in this issue and the subsequent comments: Stage2: false dependency loop · Issue #12325 · ziglang/zig · GitHub

For example,

const U = union {
    u: foo(U),
};

fn foo(T: type) type {
    return [@sizeOf(T)]u8;
}

test {
    var u: U = undefined;
    _ = &u;
}
repro.zig:1:11: error: union 'repro.U' depends on itself
const U = union {
          ^~~~~

Since you mention mixins and metaprogramming it’s very likely that introducing those into the mix is causing the compile error.

From the linked issue and related ones it seems like this happens because currently only container types (structs, unions, enums and opaques) are resolved lazily.

1 Like