Can anyone explain this?

Nicholas Wilson iamthewilsonator at hotmail.com
Tue Jun 5 09:58:43 UTC 2018


On Tuesday, 5 June 2018 at 09:03:03 UTC, Simen Kjærås wrote:
> 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.
>

Whoops I meant _is_.

> 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)):

That does seem odd but is consistent with the implicit "try" 
surrounding Dmain inserted by the runtime.

> 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.

The assert error will never be thrown because one of the 
parameters to the __assert_fail throws. Its like as if you had 
written.

if (0==1)
{
     string tmp = throwingFunc(); // throws
     __assert_fail(tmp,__LINE__,...); // dead code.
}

Actually it may be the compiler doing something funky with 
assert(0, msg); being special (assert(0,...) since the spec says 
for assert any compile time expression == 0  has the effect of 
assert(0). i.e. assert(0==1); is the same as assert(0);).

Proof


import std.stdio;
import core.exception;
bool foo() { return false;} // mess with the compiler's reasoning 
about the truthiness of the assert
void main() {
     scope(failure) {
         writeln("Not gonna happen");
     }

     try {
         static string throwingFunc() {
             throw new Exception("An exception");
         }
         assert(foo(), throwingFunc());
     } catch(Exception ex) {
         writeln("Exception");
     } catch(AssertError ex) {
         writeln("Assert");
     }
}

prints

Exception



More information about the Digitalmars-d mailing list