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:
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:
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