On Thursday, 6 September 2018 at 14:39:12 UTC, Andrei Alexandrescu wrote:
First off, there's no tree of exceptions simply because... well it's not there. There is on field "next", not two fields "left" and "right". It's a linear list, not a tree. During construction there might be the situation whereby two lists need to be merged. But they will be merged by necessity into a singly-linked list, not a tree, because we have no structural representation of a tree.

The runtime appends any exception raised by a `scope (exit|failure)` statement to the next list of an exception already being raised. So if I write:

scope (exit) throw new Exception("scope 1");
scope (exit) throw new Exception("scope 2");
throw new Exception("primary");

I get output like:

object.Exception@scratch.d(21): primary
----------------
??:? void scratch.throwy() [0x53a74c01]
??:? _Dmain [0x53a74d68]
object.Exception@scratch.d(26): scope 2
----------------
??:? void scratch.throwy() [0x53a74ce1]
??:? _Dmain [0x53a74d68]
object.Exception@scratch.d(25): scope 1
----------------
??:? void scratch.throwy() [0x53a74d42]
??:? _Dmain [0x53a74d68]

Okay, that seems reasonable. But what if each of those `scope(exit)` statements had their own chains?

scope (exit) throw new Exception("scope 1", new Exception("cause 1")); scope (exit) throw new Exception("scope 2", new Exception("cause 2"));
throw new Exception("primary");

object.Exception@scratch.d(8): primary
----------------
??:? void scratch.throwy() [0x7259caf3]
??:? _Dmain [0x7259cc64]
object.Exception@scratch.d(7): scope 2
----------------
??:? void scratch.throwy() [0x7259cba5]
??:? _Dmain [0x7259cc64]
object.Exception@scratch.d(7): cause 2
object.Exception@scratch.d(6): scope 1
----------------
??:? void scratch.throwy() [0x7259cc4c]
??:? _Dmain [0x7259cc64]
object.Exception@scratch.d(6): cause 1

The actual structure of the exceptions: `primary` has children `scope 2` and `scope 1`; `scope 2` has child `cause 2`; `scope 1` has child `cause 1`. A tree.

The encoded structure: a linked list where only the first two positions have any structure-related meaning and the rest are just a sort of mish-mash.

This isn't a situation you get in Java because Java doesn't have a way to enqueue multiple independent actions at the end of the same block. You just have try/finally and try(closeable).

(As an aside, it does seem we could allow some weird cases where people rethrow some exception down the chain, thus creating loops. Hopefully that's handled properly.)

Not if you semi-manually create the loop:

auto e = new Exception("root");
scope (exit) throw new Exception("scope 1", e);
throw e;

Filed as https://issues.dlang.org/show_bug.cgi?id=19231

Reply via email to