On Tuesday, 5 June 2018 at 08:26:22 UTC, Nicholas Wilson wrote:
writeln("Assert"); // this is not caught because the thrown
throwable is not an exception
Now that's plain false - If you replace the call to
throwingFunc() with a string literal, you'll see it's properly
caught. Also, the catch clause explicitly specifies AssertError,
which as the name implies, is an Error, not an Exception.
This might just be a case of undefined behavior. According to
https://dlang.org/spec/contracts.html:
"As a contract, an assert represents a guarantee that the code
must uphold. Any failure of this expression represents a logic
error in the code that must be fixed in the source code. A
program for which the assert contract is false is, by definition,
invalid, and therefore has undefined behaviour."
In short, what you're doing is UB, and the nasal demons are
printing 'not gonna happen' to your console.
That also makes some sense with Andrea Fontana's comments:
- Do not have side effects in either AssignExpression that
subsequent code depends on.
- Do not attempt to resume normal execution after an Assert
Failure.
However, if we add catch (Throwable ex) to the list of catch
statements, that *does* catch a regular object.Exception. Moving
the catch (Exception) statement down the list does nothing.
Adding another layer of try-catch also catches it (even with just
catch (Exception ex)):
import std.stdio;
import core.exception;
unittest {
scope(failure) {
writeln("Not gonna happen");
}
try {
try {
static string throwingFunc() {
throw new Exception("An exception");
}
assert(0==1, throwingFunc());
} catch(AssertError ex) {
writeln("Assert");
} catch(Exception ex) {
writeln("Exception A");
}
} catch(Exception ex) {
writeln("Exception B");
}
}
So I'm stumped. It seems the exception handling is simply not
setup correctly. This could be because of UB I guess, but I'd
hope the AssertError would be thrown first in such a case.
--
Simen