Self-referencing Struct

This gives a compile error. What’s the cause?

fn Foo() type {
    const Bar = struct {
        link:   ?*Bar,  <== error: use of undeclared identifier
    };

    return struct {
        bar:    Bar,
    };
}

The following works. Moving the Bar definition completely outside also works.

fn Foo() type {
    return struct {
        const Bar = struct {
            link:   ?*Bar,
        };

        bar:    Bar,
    };
}

Try @This()

2 Likes

Because it is within a function scope. The resolution of function scope during compilation is somewhat different from that of global scope. Global scope allows the use of content declared later, while within a function, only content declared earlier is permitted. It can be solved by using @This().

4 Likes

Thanks for the suggestion. @This() works.

It seems that it should work inside a function. Pointer type has known size. It shouldn’t impact figuring out the struct layout size.

Part of a pointers type is the alignment of the pointed to, by default it’s the same alignment as the pointed to type, so it needs to analyse the pointed to, to get its alignment.

@This() gets special treatment, as it knows it is referencing itself, though I don’t immediately see why that cant be extended to using the name, probably some implementation detail that makes it difficult to do so.

Hmm. Yes, alignment is part of type resolution. I would expect the type resolution on the size and alignment of the pointer type is the same for *Bar and *@This(), otherwise the other cases of self-referencing *Bar won’t work. Looking at the error message again it seems to indicate there’s a missing symbol table at the function scope.

This is because, unlike file/type level declarations, local (in function) declarations are evaluated in order, so Bar doesnt exist as it isnt finished being evaluated.

That is the actual problem here, not what I said about alignment.

However, what I said is still true in some cases, those are just edge cases that aren’t handled properly or at all.

1 Like