On Sunday, February 24, 2019 5:42:32 AM MST Dennis via Digitalmars-d-learn wrote: > On Sunday, 24 February 2019 at 10:53:09 UTC, aliak wrote: > > But the following code is very recoverable and I don't see how > > > it's unsafe to continue executing: > There is no guarantee that a final switch throws an Error. From > what I've heard of Walter [1] (though I can't find it in the > spec), the default case in a final switch is assumed to be > unreachable, so in optimized (non-safe release) code you might > just go out of bounds of the jump table and execute garbage code > instead of catching and Error, which is only a debug facility. > > [1] https://issues.dlang.org/show_bug.cgi?id=13169
IIRC, last time I tested this, with -release, there was no SwitchError when a final switch was given a bad value, whereas there was without -release. Regardless, Errors in general are considered fatal conditions and should not normally be caught. Cleanup code such as destructors, finally blocks, and scope statements are not necessarily run when an Error (or any kind of Throwable other than an Exception) is thrown. The program is always in a bad state after an Error is thrown (it's just a question of how bad), and by definition, your program is an undefined state if you catch an Error and attempt to continue. One example of this is that nothrow functions cannot throw Exceptions, but they can throw all other kinds of Throwables, and the compiler is not going to put proper exception handling code around a call to a nothrow function (if it did, that would defeat one of the main purposes of a function being nothrow). So, while the compiler doesn't guarantee that any cleanup code is run when an Error is thrown (but it still may happen in some cases), it definitely won't be run in the case of nothrow functions. So, the state of the program just becomes that much more invalid as an Error propagates its way up the stack. Errors are intended for fatal or unrecoverable conditions such as bad program logic or running out of memory and as such are really just there to print the error message and stack trace before killing the program. They are _not_ intended to be recovered from. So, it is almost never the case that code should be catching them. If you have a final switch statement, it's up to you to guarantee that the variable contains a valid enum value. If it doesn't, you have a bug in your program that needs to be fixed, regardless of whether a SwitchError is thrown or whether the program goes and does something wonky, because the debugging check that results in the SwitchError was not compiled in. Even if a SwitchError were always thrown on bad input (just like RangeErrors are always thrown for out-of-bounds array indexing in @safe functions), it would still be a programming bug that needed to be fixed. Code should not be trying to catch an Error and continue. Rather, if an Error is thrown, that means that the code has a bug that needs to be fixed. - Jonathan M Davis