Why is SwitchError an error and how is it unsafe to continue after catching it?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Sun Feb 24 23:58:52 UTC 2019


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





More information about the Digitalmars-d-learn mailing list