Recursive Struct definition in `comptime` function

I’ve recently run into a curious type resolution issue when attempting to define a recursive struct in a comptime function.

If I post the following definition as a top-level declaration, there are no issues in type resolution:

const Node = union(enum) {
    internal: struct {
        context: usize,
        children_buffer: *[64]Node,
        children: []Node,
    },
    leaf: struct {
        value: usize,
        context: usize,
    },
};

However, if this same definition is put inside a function, the Node reference in the internal struct’s fields now fail to resolve:

pub fn Tree(max_children: comptime_int, Context: type, Value: type) type {
    _ = max_children;
    _ = Context;
    _ = Value;
    const Node = union(enum) {
        internal: struct {
            context: usize,
            children_buffer: *[64]Node,
            children: []Node,
        },
        leaf: struct {
            value: usize,
            context: usize,
        },
    };
    return Node;
}

with the error use of undeclared identifier ‘Node’.

Is there a reason for this restriction, and/or is there any way to define such a recursive struct definition inside a function?

2 Likes

Because you are in a function, declarations are order dependent, so you can’t refer to Node inside its creation as it technically doesn’t exist yet.

Use @This() instead.

2 Likes

@This will in this case refer only to the internal struct type, not the overall Node definition. Is there any way I can reference the Node?

Edit: just realized I can make a declaration with @This inside of the Node tagged union, which will neatly resolve this issue. Thank you!

1 Like

you can

const Node = union(enum) {
    const Outer = @This();
    internal: struct {
        context: usize,
        children_buffer: *[64]Outer,
        children: []outer,
    },
    leaf: struct {
        value: usize,
        context: usize,
    },
};
2 Likes