(Note: Looks like there is a bug regarding Error.bypassedException member. Would others please confirm.)

On 12/12/2016 01:15 PM, Yuxuan Shui wrote:
> I read https://dlang.org/spec/statement.html, which told me that Error
> is different in the way it's chained. But that is pretty vague, and I'm
> still confused.
>
> Can someone explain that using examples?
>
> Thanks.

You're referring to "[Errors] bypass the normal chaining mechanism, such that the chain can only be caught by catching the first Error." What it means is that an Error cannot be a collateral of an Exception, hiding in its chain. So, when there is an Error that would otherwise be a collateral of an Exception, you cannot catch the original Exception. What is more importantly in-flight at that time is the Error.

The following program causes a chain of exceptions:

import std.stdio;
import std.string;
import std.range;

class TestException : Exception {
    this(string msg) {
        const fullMmsg = format("%s: %s",typeof(this).stringof, msg);
        writefln("throwing '%s'", fullMmsg);
        super(fullMmsg);
    }
}

class TestError : Error {
    this(string msg) {
        const fullMmsg = format("%s: %s",typeof(this).stringof, msg);
        writefln("throwing '%s'", fullMmsg);
        super(fullMmsg);
    }
}

// Causes an exception chain where the node at index errorIndex is an
// Error (others are all Exceptions).
void causeExceptionChain(size_t chainLength, size_t errorIndex) {
    void throws(size_t n) {
        scope (exit) {
            const msg = format("%s", n);
            if (n == errorIndex) {
                throw new TestError(msg);
            }
            else {
                throw new TestException(msg);
            }
        }

        if (n != 0) {
            // Redundant 'return' keyword due to
            // https://issues.dlang.org/show_bug.cgi?id=16960
            return throws(n - 1);
        }
    }

    throws(chainLength - 1);
}

void main() {
    try {
        // -1 would mean "no Error in the chain". Change this to a
        // number between 0 and 4 (inclusive) then you will realize
        // that the Exception below will not be caught.
        size_t errorIndex = -1;
        causeExceptionChain(5, errorIndex);
    }
    catch (Exception original) {
        writefln("Caught");
        // Unrelated: If you're not familiar with the curly braces in
        // the for loop, see the Note under "The sections of the for
        // loop" section at http://ddili.org/ders/d.en/for.html
for ({ size_t i; Throwable ex = original; } ex; ex = ex.next, ++i) {
            writeln(" ".replicate(i), ex.msg);
        }
    }
}

throwing 'TestException: 0'
throwing 'TestException: 1'
throwing 'TestException: 2'
throwing 'TestException: 3'
throwing 'TestException: 4'
Caught
TestException: 0
 TestException: 1
  TestException: 2
   TestException: 3
    TestException: 4

Make errorIndex something other than -1 e.g. 3 and you will see that the Exception cannot be caught.

        size_t errorIndex = 3;

You get the usual stack trace of an uncaught exception.

throwing 'TestException: 0'
throwing 'TestException: 1'
throwing 'TestException: 2'
throwing 'TestError: 3'
throwing 'TestException: 4'
deneme.TestError@(0): TestError: 3
----------------
[...]

Then, replace Exception with Error in the catch clause, and you will see that Error is again caught. (Side note: Errors are not supposed to be caught by programs because the whole state of the program is in question.)

    catch (Error original) {    // <-- Now Error
        // ...
    }

You will see that Error is in its own chain. It will contain just Error 3 and Error 4:

throwing 'TestException: 0'
throwing 'TestException: 1'
throwing 'TestException: 2'
throwing 'TestError: 3'
throwing 'TestException: 4'
Caught
TestError: 3
 TestException: 4

Now you would hope to get the original bypassed Exception chain with the following code

writefln("The bypassed exception was '%s'", original.bypassedException);

But bypassedException member of Error is always null. Bug?

Thank you,
Ali

Reply via email to