Second draft: Sum Type by Struct
Richard (Rikki) Andrew Cattermole
richard at cattermole.co.nz
Sat Sep 5 14:54:55 UTC 2026
On 06/09/2026 2:19 AM, Nick Treleaven wrote:
> On Friday, 4 September 2026 at 08:20:42 UTC, Richard (Rikki) Andrew
> Cattermole wrote:
>> On 04/09/2026 7:30 PM, Meta wrote:
>>> 4. Match arms being allowed to return separate types and silently
>>> evaluating to a newly synthesized sumtype is just asking for trouble.
>>> It's going to be a source of a lot of frustration and compiler
>>> errors, and potentially even bugs.
>
> I also think an inferred sumtype result is surprising. What if I want
> the result type of the match expression to be inferred from the common
> type of all the results, how would I even write that? I think inferred
> common type should be the default, which is consistent with the `?`
> operator.
You would add the casts to each arm.
> There should be some way to manually specify the result type (which
> could be a sum type or not), the compiler is not always going to get the
> desired type whatever the rules. E.g. `expr.match -> int { ... }`. And
> it would indeed be nice to allow that result type to be another sum type.
```d
int res = st.match {
(T v) => "str",
(U v) => 2
}; // error
```
Sumtypes widen on assignment, so that isn't an issue if you want a sumtype.
The match narrows to a single type, just like a sumtype of one variant
becomes that variant's type.
It doesn't need more syntax, especially one that I haven't spotted in
other languages.
> Also, using a new set of integer promotion rules (however nice) that
> aren't compatible with the C rules D inherited would need much stronger
> justification, and I doubt its a good idea. That plus sum type inference
> makes this DIP more complicated, and those could be added later in a
> separate DIP, if needed.
I'm not working from C's promotion rules here, they are primarily for
math expressions which this is not.
The rules I have worked based upon is the sumtype variants where
multiple integer types are errors for unnamed variants. You can't know
which variant to construct.
So I want a rule that is neither lossy, nor will trigger this error.
And no, flow sensitive typing is not something you "add on later". You
do it up front or not at all.
This is how you get a compiler who can't do effects analysis, but tries
to do so anyway and gets it wrong enough times that people coin the term
"attribute soup". Only after 25 years does somebody go hey we actually
can't do this and to fix it would require a full rewrite.
>> TypeScript:
>>
>> ```typescript
>> function evaluateArm(input: "a" | "b"): string | number {
>> switch (input) {
>> case "a":
>> return 42; // This arm evaluates to a number (int)
>> case "b":
>> return "hello"; // This arm evaluates to a string
>> }
>> }
>
> I don't know TS, but it looks like the `switch` above does not have a
> result type at all. BTW I am concerned that IIUC the above pattern
> (which you chose to quote), cannot be written with your proposal,
> because it doesn't support `return` in a match arm (i.e. returning from
> `evaluateArm` directly).
I wanted statement arm bodies, it was in previous designs.
But yeash there is nothing in the expression tree that would allow it
(that I could find, or aware of).
It would be a massive addition.
We could add it later on, since expression just becomes an expression
statement.
The example is a simple example showing the flow sensitivity of matching.
More information about the dip.development
mailing list