Skip to content

Proposal: Non-exhaustive tagged unions #8162

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
tadeokondrak opened this issue Mar 6, 2021 · 4 comments
Open

Proposal: Non-exhaustive tagged unions #8162

tadeokondrak opened this issue Mar 6, 2021 · 4 comments
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@tadeokondrak
Copy link
Contributor

Currently, tagged unions with a non-exhaustive enum tag don't have the forwards-compatibility features in switches, because it's impossible to create a non-existent union value.

From the non-exhaustive enums proposal:

A non-exhaustive enum is an enum that may have other unknown members.
This can help create APIs that may be extended in future. This sort of thing frequently comes up in data formats, network protocols, and even C APIs.

Non-exhaustive tagged unions can be useful in pure Zig APIs where new variants can be added, but breaking user code on updates is undesirable.

@Vexu Vexu added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Mar 6, 2021
@Vexu Vexu added this to the 0.8.0 milestone Mar 6, 2021
@ifreund
Copy link
Member

ifreund commented Mar 6, 2021

For what it's worth, I have a real world use-case for this in zig-wayland. The only alternative I see is making basically everything in the API generic over the version, which seems very heavy handed.

@SpexGuy
Copy link
Contributor

SpexGuy commented Mar 7, 2021

How would this work? Are unnamed values implicitly void or is there a way to attach payload types to them? If the latter, how is the size of the union determined?

@tadeokondrak
Copy link
Contributor Author

How would this work? Are unnamed values implicitly void or is there a way to attach payload types to them? If the latter, how is the size of the union determined?

It isn't meant to be ABI forwards-compatible like non-exhaustive enums.
The purpose is to make a user of the type decide between else => {} (staying forwards-compatible) and _ => {} (rejecting it, meaning possible compile errors on library updates).

I don't think it should be possible to create an unnamed/invalid value, so actually hitting the _ branch would be illegal behaviour.
That means any code inside the switch would be unreachable, so maybe clearer syntax for that could be added:

switch (x) {
    .a => |a| {},
    .b => |b| {},
    _,
}

@andrewrk andrewrk modified the milestones: 0.8.0, 0.9.0 May 19, 2021
@Vexu
Copy link
Member

Vexu commented Jun 10, 2021

This feature has been implemented in #8163, which can be quickly updated if this is accepted.

@andrewrk andrewrk modified the milestones: 0.9.0, 0.10.0 Nov 23, 2021
@andrewrk andrewrk modified the milestones: 0.10.0, 0.11.0 Apr 16, 2022
@andrewrk andrewrk modified the milestones: 0.11.0, 0.12.0 Apr 9, 2023
@andrewrk andrewrk modified the milestones: 0.13.0, 0.12.0 Jul 9, 2023
@andrewrk andrewrk modified the milestones: 0.14.0, 0.15.0 Feb 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

5 participants