Get sizeOf the active field of a tagged union?

The only way I can think of is a switch with every item in the union, however it is very large, and a switch would be ~80 lines of code that I don’t want. I also need to access the enum value of the tag.

See static dispatch pattern from Zig Patterns:

4 Likes

I mention this because it may or may not be important: every variant of a tagged union is the same size.

The value alone can of course vary in the size it would need if it were just that value. But the tagged union itself will always be the same size, which you can obtain with @sizeOf(TaggedUnion).

To get enum from union(enum) you can use std.meta.Tag.

fn activeFieldSize(u: anytype) usize {
    return switch (u) {
        inline else => |field| @sizeOf(@TypeOf(field)),
    };
}

This generates a switch with your ~80 prongs.

When you would use this function, I have no idea. Are you sure you want to be using a tagged union?

10 Likes

For reference: Documentation - The Zig Programming Language

In case anyone is curious, this is what a switch with 88 prongs compiles to:

2 Likes

I was wondering why the compiler isn’t able to contract the entire table to a single constant value until I noticed that the tagged union also uses different types than usize :slight_smile:

…when all items have the same size it does indeed collapse to ‘nothing’:

3 Likes

Also interesting: when the tagged union items are sorted by size, the compiler might also be able to avoid a table (e.g. in this case all the byte-sized items are at the end)

2 Likes

Looks like a missed optimization in LLVM because as far as I can tell it would be legal for the backend to re-order switch prongs.

Still, it’s impressive :slight_smile:

1 Like

But the order is established by the enum connected to tagged union. “Deborah was a Catholic girl” has to be the first prong.

Not sure what you mean - it’s clearly a pure function.

The enum is defined by the definition of the union. So the first item is “Deborah was a Catholic girl”, and second item is “She held out til the bitter end “, and so on. There’s no freedom to reorder the prongs because it’s a tagged union.

mm, I see, it’s not really switch prong order, it’s the fact that while yes it’s a pure function, the pure function has to map different inputs to different outputs depending on the field orders.

It’s hilarious that we’re having a programming discussion on Deborah being a Catholic girl. Humor is important.

There’s freedom to test for the three ‘special’ values and otherwise return @sizeOf(usize) though, because the options are disjoint and therefore the result would be equivalent.

Should it? Eh, maybe? It says ReleaseSmall on the label and that would generate smaller code for sure. But also undoubtedly less efficient, given the null hypothesis of an even data distribution of the test cases in use.

So some LLVM cost function came to this conclusion, it’s tough to call an outcome like this “wrong”, at least straightforwardly. We don’t actually want ReleaseSmall to mean “accept every pessimization so long as it makes the binary smaller”, I don’t think.

3 Likes