Stream: compiler development

Topic: zig compiler - optimized tag unions


view this post on Zulip Richard Feldman (Feb 03 2025 at 02:38):

something I'd like to not port over from our current implementation is tag union optimizations other than the specific case of single-tag unions getting unwrapped

view this post on Zulip Richard Feldman (Feb 03 2025 at 02:41):

the reason for this is that tag unions which compile to a normal tagged union are very straightforward to generate glue for, whereas right now tag unions are super hard to generate glue for because we have around 4 or 5 completely different representations we compile to

view this post on Zulip Richard Feldman (Feb 03 2025 at 02:42):

at the time we didn't realize what effect they would have on glue (glue didn't actually exist at the time) but now with the benefit of hindsight I think they're not worth it

view this post on Zulip Brendan Hansknecht (Feb 03 2025 at 02:42):

What is the plan for recursive tags?

view this post on Zulip Richard Feldman (Feb 03 2025 at 02:42):

they have to be nominal

view this post on Zulip Richard Feldman (Feb 03 2025 at 02:42):

those are different - in that case it's not an optimization, we just have to do special heap stuff unavoidably

view this post on Zulip Brendan Hansknecht (Feb 03 2025 at 02:47):

I would have to relook over the tag types, but I think this makes sense. I think most of the complex forms relate to recursive tags anyway.

I assume we would make all tags be equivalent (enough bytes for all fields with max field alignment, tag id). If there are no fields, this would become only tag id.

view this post on Zulip Brendan Hansknecht (Feb 03 2025 at 02:48):

And the only exception is single tags which are represented as the underlying type.

view this post on Zulip Richard Feldman (Feb 03 2025 at 02:50):

yep!

view this post on Zulip Brendan Hansknecht (Feb 03 2025 at 02:50):

what about box? Make it a bespoke builtin type?

view this post on Zulip Richard Feldman (Feb 03 2025 at 02:50):

yeah just like today

view this post on Zulip Brendan Hansknecht (Feb 03 2025 at 02:51):

I think it is currently the main (only?) use of NonNullableWrapped tags

view this post on Zulip Brendan Hansknecht (Feb 03 2025 at 02:51):

today, box is actually a tag, not a standalone type.

view this post on Zulip Richard Feldman (Feb 03 2025 at 02:52):

ha, TIL!

view this post on Zulip Richard Feldman (Feb 03 2025 at 02:52):

yeah I think it should be standalone

view this post on Zulip Richard Feldman (Feb 03 2025 at 02:52):

doesn't it need special semantics when you put a closure in it? :thinking:

view this post on Zulip Richard Feldman (Feb 03 2025 at 02:53):

maybe that has never worked, which would explain the problems with trying to pass Boxed closures to the host :sweat_smile:

view this post on Zulip Brendan Hansknecht (Feb 03 2025 at 02:53):

I don't think boxed closures work today

view this post on Zulip Richard Feldman (Feb 03 2025 at 02:54):

that representation would certainly explain why!

view this post on Zulip Brendan Hansknecht (Feb 03 2025 at 02:59):

Yeah, from looking at the tag variants, we have:

view this post on Zulip Brendan Hansknecht (Feb 03 2025 at 03:00):

Unwrapped means you don't need a tag id (either only one variant or two variants with one being null)

view this post on Zulip Brendan Hansknecht (Feb 03 2025 at 03:00):

and Nullable meaning it can be null

view this post on Zulip Brendan Hansknecht (Feb 03 2025 at 03:02):

I'm sure these matter for classic cons lists. I'm not sure how much they matter for other structures. I would assume a tree that instead of using lists uses a specific number of nodes in a tag could gain value from some of these patterns, but not sure that really matters for normal roc code. Recursive tags are pretty rare in roc due to the basis being flat lists

view this post on Zulip Brendan Hansknecht (Feb 03 2025 at 03:04):

If we were to keep any of these optimization, I think we would only want to keep tagged pointers if we have less than N tags. That is likely to make a meaningful perf impact due to being able to check the tag id without following a pointer indirection. I don't think any of the other changes would have significant gains over that.

view this post on Zulip Brendan Hansknecht (Feb 03 2025 at 03:06):

Also, are we planning to allow recursive types without tags? Like Node a: List (U64, Node a)

view this post on Zulip Brendan Hansknecht (Feb 03 2025 at 03:06):

Totally fine if it requires being nominal, but I think that is a common annoying case to hit in the current compiler.

view this post on Zulip Richard Feldman (Feb 03 2025 at 03:08):

no, Ayaz wrote a thing (I forget where) about how they cause a big problem

view this post on Zulip Richard Feldman (Feb 03 2025 at 03:09):

and the best solution seems to be disallowing them

view this post on Zulip Richard Feldman (Feb 03 2025 at 03:09):

that was the main motivation for replacing opaque types with custom tag unions

view this post on Zulip Richard Feldman (Feb 03 2025 at 03:09):

(well, the original motivation)

view this post on Zulip Richard Feldman (Feb 03 2025 at 03:10):

so that we could still have recursive sum types that could be passed to the host (which opaque types can't)

view this post on Zulip Richard Feldman (Feb 03 2025 at 03:11):

anyway, we can always reintroduce some number of these in the future if we want to, but right now I think it's way more important to get reliable, working glue

view this post on Zulip Brendan Hansknecht (Feb 03 2025 at 03:22):

This:

Richard Feldman: no, Ayaz wrote a thing (I forget where) about how they cause a big problem

Richard Feldman: and the best solution seems to be disallowing them

Is in response to this?

Also, are we planning to allow recursive types without tags? Like Node a: List (U64, Node a)

correct?

view this post on Zulip Brendan Hansknecht (Feb 03 2025 at 03:22):

If so, what would the equivalent look like with nominal types?


Last updated: Jul 06 2025 at 12:14 UTC