digitalmars.D - Collateral Exceptions, Throwable vs Exception
- Andrej Mitrovic (56/56) Aug 19 2010 TDPL code that should work:
- Vladimir Panteleev (9/10) Aug 19 2010 That reminds me, the code on http://digitalmars.com/d/2.0/windows.html
- Sean Kelly (9/14) Aug 19 2010 Because e.next is a Throwable reference inherited from Throwable:
- Andrej Mitrovic (4/21) Aug 19 2010 That goes against the statement in TDPL that user code should never catc...
- Andrei Alexandrescu (6/9) Aug 19 2010 Indirectly, yes (I'm not positive about this detail though): if an
- Sean Kelly (9/12) Aug 19 2010 You should avoid explicitly catching Throwable, but I can see what you'r...
- Andrej Mitrovic (15/42) Aug 19 2010 Actually, would this be safe to use? :
- Stanislav Blinov (9/25) Aug 19 2010 I'm no expert, but why shouldn't? I'd propose a correction though:
- Andrej Mitrovic (5/29) Aug 19 2010 The problem is in the e =3D e.next assignment, not in the code block bel...
- Stanislav Blinov (2/31) Aug 19 2010 *slap in the head* Silly me.
- Andrej Mitrovic (3/4) Aug 19 2010 Damn gmail and formatting. I hope that last message wasn't garbled.
- Andrei Alexandrescu (5/19) Aug 19 2010 Sean's right. And thanks Sean and Walter for implementing the exceptions...
- Andrej Mitrovic (18/48) Aug 19 2010 Yes, I've added it as Throwable. But there's one more problem with
- Sean Kelly (2/20) Aug 19 2010 Are these stack trace lines or actual distinct exceptions?
- Andrej Mitrovic (20/40) Aug 19 2010 I think I found the problem. e contains all the collateral exceptions
- Sean Kelly (2/47) Aug 19 2010
- Mike Parker (10/12) Aug 19 2010 IMO, it should be the opposite. I noticed the current behavior the other...
- Andrei Alexandrescu (5/20) Aug 19 2010 My opinion: Throwable should have a @property called printingDepth or
- Mike Parker (2/25) Aug 20 2010 Yes, that's better. +1.
- Andrei Alexandrescu (3/18) Aug 19 2010 The reverse ordering seems to be a bug in the implementation.
- Steven Schveighoffer (7/28) Aug 23 2010 Don't have the book in front of me, but it is important that collateral ...
- Kagamin (4/8) Aug 19 2010 Can it be fixed with compiler calling, say,
TDPL code that should work: class MyException : Exception { this(string s) { super(s); } } void fun() { try { throw new Exception("thrown from fun"); } finally { gun(100); } } void gun(int x) { try { } finally { if (x > 1 ) { gun(x - 1); } } } import std.stdio, std.conv; unittest { try { fun(); } catch (Exception e) { writeln("Primary exception: ", typeid(e), " ", e); while ((e = e.next) !is null) { writeln("Collateral exception: ", typeid(e), " ", e); } } } void main() { } Errors out: (49): Error: cannot implicitly convert expression (e.next) of type object.Throwable to object.Exception Why would the return type of e.next be Throwable if e is an Exception type? I've tried casting e.next to type Exception, but that creates an entire mess.
Aug 19 2010
On Thu, 19 Aug 2010 22:43:59 +0300, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:TDPL code that should work:That reminds me, the code on http://digitalmars.com/d/2.0/windows.html doesn't compile as well. You need to change the signature of the exceptionHandler function (replace Exception with Throwable) for it to compile. -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Aug 19 2010
Andrej Mitrovic Wrote:TDPL code that should work:...Errors out: (49): Error: cannot implicitly convert expression (e.next) of type object.Throwable to object.Exception Why would the return type of e.next be Throwable if e is an Exception type?Because e.next is a Throwable reference inherited from Throwable: class Throwable { Throwable next; } class Error : Throwable {} class Exception : Throwable {} Because collateral exceptions could be both Errors and Exceptions, I don't think the sample code can work exactly as written.
Aug 19 2010
That goes against the statement in TDPL that user code should never catch Throwable's, unless absolutely necessary. So in case of collateral exceptions, we are forced to catch Throwable anyway? On Thu, Aug 19, 2010 at 10:00 PM, Sean Kelly <sean invisibleduck.org> wrote:Andrej Mitrovic Wrote:TDPL code that should work:...Errors out: (49): Error: cannot implicitly convert expression (e.next) of typeobject.Throwable to object.ExceptionWhy would the return type of e.next be Throwable if e is an Exceptiontype? Because e.next is a Throwable reference inherited from Throwable: class Throwable { Throwable next; } class Error : Throwable {} class Exception : Throwable {} Because collateral exceptions could be both Errors and Exceptions, I don't think the sample code can work exactly as written.
Aug 19 2010
On 08/19/2010 03:18 PM, Andrej Mitrovic wrote:That goes against the statement in TDPL that user code should never catch Throwable's, unless absolutely necessary. So in case of collateral exceptions, we are forced to catch Throwable anyway?Indirectly, yes (I'm not positive about this detail though): if an Exception is in flight but a Throwable was produced as collateral damage, the Throwable won't disobey normal scoping rules etc. so it won't be "special" anymore. Andrei
Aug 19 2010
Andrej Mitrovic Wrote:That goes against the statement in TDPL that user code should never catch Throwable's, unless absolutely necessary. So in case of collateral exceptions, we are forced to catch Throwable anyway?You should avoid explicitly catching Throwable, but I can see what you're getting at: if a collateral exception is an Error then it should not be ignored. You could always do something like this: catch (Exception e) { for (Throwable t = e; t; t = t.next) { if (cast(Error) t) throw t; // collateral damage critical! writeln(t); } }
Aug 19 2010
Actually, would this be safe to use? : try { fun(); } catch (Exception e) { writeln("Primary exception: ", typeid(e)); while ((e = cast(Exception)e.next) !is null) { writeln("Collateral exception: ", typeid(e)); } } On Thu, Aug 19, 2010 at 10:18 PM, Andrej Mitrovic < andrej.mitrovich gmail.com> wrote:That goes against the statement in TDPL that user code should never catch Throwable's, unless absolutely necessary. So in case of collateral exceptions, we are forced to catch Throwable anyway? On Thu, Aug 19, 2010 at 10:00 PM, Sean Kelly <sean invisibleduck.org>wrote:Andrej Mitrovic Wrote:TDPL code that should work:...Errors out: (49): Error: cannot implicitly convert expression (e.next) of typeobject.Throwable to object.ExceptionWhy would the return type of e.next be Throwable if e is an Exceptiontype? Because e.next is a Throwable reference inherited from Throwable: class Throwable { Throwable next; } class Error : Throwable {} class Exception : Throwable {} Because collateral exceptions could be both Errors and Exceptions, I don't think the sample code can work exactly as written.
Aug 19 2010
Andrej Mitrovic wrote:Actually, would this be safe to use? : try { fun(); } catch (Exception e) { writeln("Primary exception: ", typeid(e)); while ((e = cast(Exception)e.next) !is null) { writeln("Collateral exception: ", typeid(e)); } }I'm no expert, but why shouldn't? I'd propose a correction though: while ((e = e.next) !is null) { if (cast(Exception)e) { writeln(/*whatever*/); } }
Aug 19 2010
The problem is in the e =3D e.next assignment, not in the code block below = it. On Thu, Aug 19, 2010 at 10:42 PM, Stanislav Blinov <stanislav.blinov gmail.com> wrote:Andrej Mitrovic wrote:l)Actually, would this be safe to use? : =A0 =A0try =A0 =A0{ =A0 =A0 =A0 =A0fun(); =A0 =A0} =A0 =A0catch (Exception e) =A0 =A0{ =A0 =A0 =A0 =A0writeln("Primary exception: ", typeid(e)); =A0 =A0 =A0 =A0 =A0 =A0 =A0 while ((e =3D cast(Exception)e.next) !is nul==A0 =A0 =A0 =A0{ =A0 =A0 =A0 =A0 =A0 =A0writeln("Collateral exception: ", typeid(e)); =A0 =A0 =A0 =A0} =A0 =A0 }I'm no expert, but why shouldn't? I'd propose a correction though: while ((e =3D e.next) !is null) { =A0 =A0if (cast(Exception)e) =A0 =A0{ =A0 =A0 =A0 =A0writeln(/*whatever*/); =A0 =A0} }
Aug 19 2010
Andrej Mitrovic wrote:The problem is in the e = e.next assignment, not in the code block below it. On Thu, Aug 19, 2010 at 10:42 PM, Stanislav Blinov <stanislav.blinov gmail.com> wrote:*slap in the head* Silly me.Andrej Mitrovic wrote:Actually, would this be safe to use? : try { fun(); } catch (Exception e) { writeln("Primary exception: ", typeid(e)); while ((e = cast(Exception)e.next) !is null) { writeln("Collateral exception: ", typeid(e)); } }I'm no expert, but why shouldn't? I'd propose a correction though: while ((e = e.next) !is null) { if (cast(Exception)e) { writeln(/*whatever*/); } }
Aug 19 2010
Damn gmail and formatting. I hope that last message wasn't garbled. On Thu, Aug 19, 2010 at 10:25 PM, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:Actually, would this be safe to use? :
Aug 19 2010
On 08/19/2010 03:00 PM, Sean Kelly wrote:Andrej Mitrovic Wrote:Sean's right. And thanks Sean and Walter for implementing the exceptions spec properly, I believe it's very important to the success of D. Andrej... sounds like another errata entry, please :o). AndreiTDPL code that should work:...Errors out: (49): Error: cannot implicitly convert expression (e.next) of type object.Throwable to object.Exception Why would the return type of e.next be Throwable if e is an Exception type?Because e.next is a Throwable reference inherited from Throwable: class Throwable { Throwable next; } class Error : Throwable {} class Exception : Throwable {} Because collateral exceptions could be both Errors and Exceptions, I don't think the sample code can work exactly as written.
Aug 19 2010
Yes, I've added it as Throwable. But there's one more problem with your code, this: catch (Throwable e) // have to use Throwable for collateral exceptions // or maybe use a cast like below { writeln("Primary exception: ", typeid(e), " ", e); while ((e =3D e.next) !is null) { writeln("Collateral exception: ", typeid(e), " ", e); } } Will output ~5000 lines of "Exception .." stuff. Oh and in the book it looks like you're counting from 100 to 1 (for the throws from gun), which makes sense. Yet I'm getting back output from 1 to 100. Not sure what's going on there.. On Thu, Aug 19, 2010 at 10:32 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:On 08/19/2010 03:00 PM, Sean Kelly wrote:'tAndrej Mitrovic Wrote:TDPL code that should work:...Errors out: (49): Error: cannot implicitly convert expression (e.next) of type object.Throwable to object.Exception Why would the return type of e.next be Throwable if e is an Exception type?Because e.next is a Throwable reference inherited from Throwable: class Throwable { =A0 =A0 Throwable next; } class Error : Throwable {} class Exception : Throwable {} Because collateral exceptions could be both Errors and Exceptions, I don=think the sample code can work exactly as written.Sean's right. And thanks Sean and Walter for implementing the exceptions spec properly, I believe it's very important to the success of D. Andrej... sounds like another errata entry, please :o). Andrei
Aug 19 2010
Andrej Mitrovic Wrote:Yes, I've added it as Throwable. But there's one more problem with your code, this: catch (Throwable e) // have to use Throwable for collateral exceptions // or maybe use a cast like below { writeln("Primary exception: ", typeid(e), " ", e); while ((e = e.next) !is null) { writeln("Collateral exception: ", typeid(e), " ", e); } } Will output ~5000 lines of "Exception .." stuff. Oh and in the book it looks like you're counting from 100 to 1 (for the throws from gun), which makes sense. Yet I'm getting back output from 1 to 100. Not sure what's going on there..Are these stack trace lines or actual distinct exceptions?
Aug 19 2010
I think I found the problem. e contains all the collateral exceptions (in a linked list according to TDPL), and printing out e will print out each and every collateral exception. So if that's the case, there's no point to using that while loop. But if we can't print out only one exception from a linked list, then what is the point of the .next property? This prints out the all the collateral exceptions: try { fun(); } catch (Throwable e) { writeln(e); } On Thu, Aug 19, 2010 at 11:11 PM, Sean Kelly <sean invisibleduck.org> wrote= :Andrej Mitrovic Wrote:ptionsYes, I've added it as Throwable. But there's one more problem with your code, this: catch (Throwable e) =A0 =A0 // have to use Throwable for collateral exce=a cast like below=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 // or maybe use =, e);=A0 =A0 { =A0 =A0 =A0 =A0 writeln("Primary exception: ", typeid(e), " ", e); =A0 =A0 =A0 =A0 while ((e =3D e.next) !is null) =A0 =A0 =A0 =A0 { =A0 =A0 =A0 =A0 =A0 =A0 writeln("Collateral exception: ", typeid(e), " "==A0 =A0 =A0 =A0 } =A0 =A0 } Will output ~5000 lines of "Exception .." stuff. Oh and in the book it looks like you're counting from 100 to 1 (for the throws from gun), which makes sense. Yet I'm getting back output from 1 to 100. Not sure what's going on there..Are these stack trace lines or actual distinct exceptions?
Aug 19 2010
The .next property is to allow chaining. However, it may be that the current behavior of toString is incorrect, or that a new function should be added that only returns a string describing the current exception and not the entire chain. Andrej Mitrovic Wrote:I think I found the problem. e contains all the collateral exceptions (in a linked list according to TDPL), and printing out e will print out each and every collateral exception. So if that's the case, there's no point to using that while loop. But if we can't print out only one exception from a linked list, then what is the point of the .next property? This prints out the all the collateral exceptions: try { fun(); } catch (Throwable e) { writeln(e); } On Thu, Aug 19, 2010 at 11:11 PM, Sean Kelly <sean invisibleduck.org> wrote:Andrej Mitrovic Wrote:Yes, I've added it as Throwable. But there's one more problem with your code, this: catch (Throwable e) // have to use Throwable for collateral exceptions // or maybe use a cast like below { writeln("Primary exception: ", typeid(e), " ", e); while ((e = e.next) !is null) { writeln("Collateral exception: ", typeid(e), " ", e); } } Will output ~5000 lines of "Exception .." stuff. Oh and in the book it looks like you're counting from 100 to 1 (for the throws from gun), which makes sense. Yet I'm getting back output from 1 to 100. Not sure what's going on there..Are these stack trace lines or actual distinct exceptions?
Aug 19 2010
Sean Kelly wrote:The .next property is to allow chaining. However, it may be that the current behavior of toString is incorrect, or that a new function should be added that only returns a string describing the current exception and not the entire chain.IMO, it should be the opposite. I noticed the current behavior the other day and was surprised. I would expect toString to return only the message from the Throwable I called it on. A concatenated string of messages from the whole chain would be the special case to be separated into a convenience function. Then again, I don't see the convenience function being necessary, as it's trivial to roll your own for the cases when you want it -- which is what I was doing when I discovered the current behavior and, like Andrej, was confronted by a long list of exception messages.
Aug 19 2010
On 08/19/2010 10:14 PM, Mike Parker wrote:Sean Kelly wrote:My opinion: Throwable should have a property called printingDepth or something. It should default to e.g. 3 (or conservatively at 1) and limit the number of exceptions in a chain formatted in toString(). AndreiThe .next property is to allow chaining. However, it may be that the current behavior of toString is incorrect, or that a new function should be added that only returns a string describing the current exception and not the entire chain.IMO, it should be the opposite. I noticed the current behavior the other day and was surprised. I would expect toString to return only the message from the Throwable I called it on. A concatenated string of messages from the whole chain would be the special case to be separated into a convenience function. Then again, I don't see the convenience function being necessary, as it's trivial to roll your own for the cases when you want it -- which is what I was doing when I discovered the current behavior and, like Andrej, was confronted by a long list of exception messages.
Aug 19 2010
Andrei Alexandrescu wrote:On 08/19/2010 10:14 PM, Mike Parker wrote:Yes, that's better. +1.Sean Kelly wrote:My opinion: Throwable should have a property called printingDepth or something. It should default to e.g. 3 (or conservatively at 1) and limit the number of exceptions in a chain formatted in toString(). AndreiThe .next property is to allow chaining. However, it may be that the current behavior of toString is incorrect, or that a new function should be added that only returns a string describing the current exception and not the entire chain.IMO, it should be the opposite. I noticed the current behavior the other day and was surprised. I would expect toString to return only the message from the Throwable I called it on. A concatenated string of messages from the whole chain would be the special case to be separated into a convenience function. Then again, I don't see the convenience function being necessary, as it's trivial to roll your own for the cases when you want it -- which is what I was doing when I discovered the current behavior and, like Andrej, was confronted by a long list of exception messages.
Aug 20 2010
On 08/19/2010 03:45 PM, Andrej Mitrovic wrote:Yes, I've added it as Throwable. But there's one more problem with your code, this: catch (Throwable e) // have to use Throwable for collateral exceptions // or maybe use a cast like below { writeln("Primary exception: ", typeid(e), " ", e); while ((e = e.next) !is null) { writeln("Collateral exception: ", typeid(e), " ", e); } } Will output ~5000 lines of "Exception .." stuff. Oh and in the book it looks like you're counting from 100 to 1 (for the throws from gun), which makes sense. Yet I'm getting back output from 1 to 100. Not sure what's going on there..The reverse ordering seems to be a bug in the implementation. Andrei
Aug 19 2010
On Thu, 19 Aug 2010 18:48:15 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:On 08/19/2010 03:45 PM, Andrej Mitrovic wrote:Don't have the book in front of me, but it is important that collateral exceptions be ordered in reverse order of insertion, otherwise, adding a collateral exception involves a linear search to the end of the linked list. -SteveYes, I've added it as Throwable. But there's one more problem with your code, this: catch (Throwable e) // have to use Throwable for collateral exceptions // or maybe use a cast like below { writeln("Primary exception: ", typeid(e), " ", e); while ((e = e.next) !is null) { writeln("Collateral exception: ", typeid(e), " ", e); } } Will output ~5000 lines of "Exception .." stuff. Oh and in the book it looks like you're counting from 100 to 1 (for the throws from gun), which makes sense. Yet I'm getting back output from 1 to 100. Not sure what's going on there..The reverse ordering seems to be a bug in the implementation.
Aug 23 2010
Andrei Alexandrescu Wrote:Indirectly, yes (I'm not positive about this detail though): if an Exception is in flight but a Throwable was produced as collateral damage, the Throwable won't disobey normal scoping rules etc. so it won't be "special" anymore.Can it be fixed with compiler calling, say, Throwable Runtime.compose(Throwable flying, Throwable thrown) ?
Aug 19 2010