I finally added bottom types to neat (https://neat-lang.github.io , but it's not on a released tag yet). For context, bottom types are called noreturn
in D. The main motivation for me was that it enables a very neat idiom for built-in sumtypes. Since someone raised the idea of making sumtypes built-in to Walter, I want to preemptively explain how this works:
(int | string) foo;
...
int i = foo.case(int i: i, string s: return null);
Now, this used to be a built-in syntax. It seems intuitively obvious that you should be able to discard a branch of the case
by just returning out of the function entirely. But the way that it actually works now, is that all block enders, ie. return
, break
and continue
, instead of statements are just - expressions of type bottom
. And bottom unifies with every type :) so these expressions don't add any type of their own to the case
expression type - except if they are the only expression in the case
, in which case the type of the whole case
expression is bottom
, as it should be.
The reason I love this so much is because it's an easy way in the typesystem to capture our intuition about these statements; which is that we can ignore them because they don't ever evaluate to an actual value. And in one stroke, it also enables other idioms, like foo.case(string s: exit(1))
, which we would expect to work the same, for the same reason.
So, you know, we already have noreturn, so if you ever implement built-in sumtypes in D, keep this in mind. :)
PS: hilariously, with this change the following is entirely valid code:
int foo() { return return return 3; }