First Draft: Nominal Sum Types via `enum union` and `switch` Expressions

Dukc ajieskola at gmail.com
Wed Sep 23 09:14:43 UTC 2026


On Monday, 21 September 2026 at 14:17:51 UTC, Meta wrote:
>> This means that `int*` is more specialised than `void*` and 
>> should therefore be picked.
>
> Ya, I meant for that to be long*, not void*.

Now sounds right to me.

>> Well you are already specifying your sum types are structs in 
>> disguise, which is likewise out of scope for what is minimally 
>> required for sum types.
>
> How else would they be represented? A struct that contains a 
> union has been the canonical way to do this for the past 50 
> years, and it's a very easy, simple lowering.

Some inprecision from my part again. I don't actually care much 
how the compiler will lower the tagged union, that's an 
implementation detail only unless you spec it. I mean your 
specification that additional (non-`case`) non-`static` fields 
will behave as in `struct`s (or `class`es).

It's not unreasonable, but it's not the only choice. The 
additional fields could alternatively behave as in a regular 
`union`s like I proposed, or the compiler might simply reject 
them. The latter choice would be the minimalist one.

>> I guess changing the keyword would be an okay alternative for 
>> me.
>
> `enum union` is just a placeholder name, but it also makes the 
> most sense to me. They have aspects of both enums, with the 
> enumerated cases, and unions, with the overlapping storage. 
> Simple.

Except the storage stops overlapping if you use non-`case` fields.

>>
>> The question is, what are_those invariants in this case? You 
>> can specify that a sum type must have a valid tag on 
>> destruction or else undefined or unspecified behaviour will 
>> follow. But I don't think that's a good idea, since it isn't 
>> possible to skip the destructor call of a local variable
>
> Named Return Value Optimization.
>

If you're returning the sumtyped value, that is. Not always the 
case.

>> (except by things like `longjmp` or foreign language 
>> exceptions). Hence my suggestion to specify the destructor 
>> will do nothing if the tag is invalid.
>
> You're wildly over-complicating this. If the user wants to mess 
> around and do @system stuff with an enum union, they're on 
> their own.

I'm not sure my suggestion is actually complicating anything. It 
is literally the simplest behaviour possible to do nothing on 
invalid tag. My suggestion would basically just ban the compiler 
from executing a random destructor on an invalid tag or the 
optimiser assuming the tag will always be valid.

>> I basically mean that if you have `switch (sum) { case x(y) => 
>> smth, ...}`, it could either mean that `x` is a variant and 
>> `y` is a variable declaration for `smth`, or that `x` is a 
>> function or a constructor called with value `y`, and `sum` is 
>> matched against the result (as in existing switch statements).
>
> It's invalid to have a function call here, so there's no 
> ambiguity.

Doesn't that feel limiting? Consider matching a primitive type. 
Do you feel this should not be allowed?

```d
import std.conv;

auto var = case(aString.front)
{
     case '\r' => fun(),
     case '\n' => gun(),
     // Unicode replacement character
     case to!dchar(0xFFFD) => hun(),
};
```

Remember, existing `switch` statements allow this. Why `switch` 
expressions wouldn't?

>
> I'm fine with that. If you think it's worthwhile, you will need 
> to show me a very convincing example of why it's useful.

```d
enum union DynamicNumber
{   case long, case float, case double, case error(string);
}

@safe sum(DynamicNumber a, DunamicNumber b) => switch(a)
{   case error(s) => a,
     case numA => switch(b)
     {   case error(s) => b,
         case numB => numA + numB,
     },
};
```

This is a lot more verbose to do manually with `static foreach`s, 
especially if you're going to stick with colon separators for the 
match cases as opposed to semicolon separators so that you can't 
place the `static foreach` inside the switch statement.


More information about the dip.development mailing list