Stream: compiler development

Topic: Why are tag union discriminants stored after the payload?


view this post on Zulip Sven van Caem (Oct 17 2024 at 16:26):

I was trying to see if I could represent roc tag unions with regular rust enums with #[repr(C)], and it looks like their memory layouts are perfectly compatible except the discriminant is stored at the end rather than the start like in Rust (or generally in C). I thought it might be to pack the discriminant in with fields of the same alignment to avoid unnecessary padding but that doesn't seem to be the case. It's got me curious about whether the ordering was an arbitrary decision? or if putting the discriminant last is advantageous somehow?

view this post on Zulip Brendan Hansknecht (Oct 17 2024 at 18:30):

It was to reduce padding.

view this post on Zulip Brendan Hansknecht (Oct 17 2024 at 18:31):

That said, implementation may be bugged or you may not be giving an example where it applies

view this post on Zulip Brendan Hansknecht (Oct 17 2024 at 18:32):

If you have something like

MyTag : [
    A I64 I32 I16 I8,
    B,
]

It should pack into 16 bytes

view this post on Zulip Brendan Hansknecht (Oct 17 2024 at 18:33):

With tag first it would need to be 24 bytes

view this post on Zulip Sven van Caem (Oct 17 2024 at 19:01):

Makes sense. It does seem to be bugged then. Roc glue reported your example's tag union's discriminantOffset to be 16, where optimally it would be 15

view this post on Zulip Sven van Caem (Oct 17 2024 at 19:04):

Should I file an issue for this?

view this post on Zulip Brendan Hansknecht (Oct 17 2024 at 19:17):

yes please

view this post on Zulip Sven van Caem (Oct 17 2024 at 19:39):

#7171


Last updated: Jul 06 2025 at 12:14 UTC