draft proposal for Sum Types for D

Jacob Carlborg doob at me.com
Tue Nov 29 20:37:57 UTC 2022


On Tuesday, 29 November 2022 at 06:26:20 UTC, Walter Bright wrote:
> Go ahead, Make My Day! Destroy!
>
> https://github.com/WalterBright/DIPs/blob/sumtypes/DIPs/1NNN-(wgb).md

### ABI

I think a section on ABI is missing. It should specify the memory 
layout of sumtypes, just as for existing language constructs [1]. 
What's even more important than the memory layout is the value of 
the tag. Something needs to be specified in regards to the value 
of the tag. One needs to be able to draw some conclusions about 
what happens with the value if members are added, removed or 
reordered. Ideally the tag value of existing members should not 
change. These are important things when using sumtypes at ABI 
boundaries.

### Checking of the Tag

The DIP mention there's a runtime check of the tag, but it 
doesn't specify what "runtime check" is. It should. Walter did 
reply to a post that it would be like a buffer overflow error 
[2]. Which is not entirely clear, but if you overflow a buffer 
(an array) it throws a RangeError, so I would guess it throws an 
Error. Yet another language construct that a has a non-obvious 
dependency on the exception handling system. This is unfortunate. 
The sumtype is a good alternative for error handling to the 
existing exception system we have today. If the sumtype is going 
to depend on the exception system this will be less attractive. A 
tagged union can be used in any system (embedded, kernel, etc.). 
If the sumtype is going to depend on the exception system it 
probably cannot be used in these environments.

It would be great if there was no hidden runtime check. Force the 
user explicitly write code that checks the tag, otherwise it's a 
compile time error to access a member. Timon already suggested 
this [3].

This could potentially be extended to allow accessing the field 
without checking the tag, but require checking the tag before 
using the value, example:

```d
sumtype Result
{
     Error,
     int Value
}

Result foo();

void bar()
{
     auto value = foo().Value; // ok, has not been used yet
     writeln(value); // compile time error to use `value`
     if (!?value)
         return;
     writeln(value); // ok, `value` has been checked above
}
```

This would allow early returns and avoid nesting all code in if 
statements. BTW, `value` now behaves more or less like an 
optional type.

### Breaking Changes

Another breaking change, perhaps an edge case, but code that 
inspects all types and language constructs and performs different 
actions, i.e. a serialization library or something like 
`writeln`. Example:

```d
static if (is(T == int)) {}
else static if (is(T == enum)) {}
// exhaustive checks of all language constructs
else
     static assert(false);
```

Or even worse, if the else statement is missing.

### Switch Statement/Pattern Matching

The DIP mentions that pattern matching is subject of another DIP. 
But I think it's reasonable that the switch statement should 
support sumtypes, in the same way as the if statement. Nothing 
fancy, just the same feature as the if statement supports.

[1] https://dlang.org/spec/abi.html
[2] https://forum.dlang.org/post/tm4kbe$23l2$1@digitalmars.com
[3] https://forum.dlang.org/post/tm55o9$mq2$3@digitalmars.com

--
/Jacob Carlborg


More information about the Digitalmars-d mailing list