Built-in sumtypes, case and noreturn: why block enders should be expressions.
Dukc
ajieskola at gmail.com
Wed Oct 26 12:07:41 UTC 2022
On Wednesday, 26 October 2022 at 05:53:21 UTC, FeepingCreature
wrote:
>> ```D
>> extern(C) Throwable abort();
>> noreturn foo() nothrow { throw abort; }
>> ```
>>
>> ...which I believe currently works. Or is that a problem too?
>
> That doesn't work. How would it? D has no idea that abort can
> never return if it's not typed `noreturn`. (Neither works, to
> be clear.)
Just tested. Yes, it doesn't work. This does, though:
```D
extern(C) Error abort();
noreturn foo() nothrow { throw abort; }
```
It works because a throw statement is always of type `noreturn`,
no matter what is thrown. If `abort` indeed aborts, fine,
obviously we don't return. However, if it did return an `Error`,
we'd then throw that, which also prevents doing anything with
"result" of `throw`. This works even in `nothrow` because we're
throwing an unrecoverable error, not an exception. This is also
why the snippet with `Throwable` does not compile - `abort` might
potentially return an `Exception`, because `Exception`s are
`Throwable`s. With an `Error` return type, that's not possible.
It makes an interesting question whether `throw throw something`
(or `throw assert(0)`) should be allowed, and if, should it be
`@safe` and/or `nothrow`? You could argue that the bottom type
converts to `Exception` and thus you can't do it in `nothrow`,
but can in `@safe`. Equally you could say the bottom type
converts to `Error`, so throwing it should be ok in `nothrow` but
not in `@safe`. Or you could say that since the execution will
never actually reach where a bottom type is instantiated, it's ok
to "throw" it anywhere.
More information about the Digitalmars-d
mailing list