Shows how scope(failure) return's can prevent proper exception bubbling.
application/octet-stream
408
Comments
Comment #0 by shammah.chancellor — 2013-11-21T18:40:30Z
It was brought to my attention that scope(failure) can prevent the bubbling of exceptions by returning from the failure statement. This is bad behavior as scope failures can unintentionally prevent other scope failures from occurring.
Comment #1 by shammah.chancellor — 2013-11-22T20:10:22Z
Created attachment 1293
Shows how scope(failure) return's can prevent proper exception bubbling.
Comment #2 by yebblies — 2013-11-23T00:23:19Z
Please paste test cases inline whenever possible.
import std.stdio;
void someFunc()
{
scope(failure) { writeln("What?");} // <-- NEVER EXECUTED?!
scope(failure) {
writeln("Failed in someFunc()");
return;
}
throw new Exception("Exception!");
}
void main() {
try {
someFunc();
writeln("Yay, someFunc() is nothrow");
} catch(Exception e) {
writeln("An exception in main!");
}
}
Comment #3 by monarchdodra — 2013-11-25T00:03:10Z
> Shows how scope(failure) return's can prevent proper exception bubbling.
"scope(failure)" doesn't return. It lives "inside" the function it is declared in. It "holds" a return statement. It "rethrows" only once at the end of its block, but you are explicitly allowed to place a control statement inside the scope to *not* rethrow. An example case would be:
//----
import std.stdio;
void main()
{
foreach(i ; 0 .. 10)
{
scope(failure)
continue; //Ignore exception and power through
writeln(i);
throw new Exception("");
}
writeln("done!");
}
//----
Another example could be an "Exception to return code" case:
//----
HRESULT foo() nothrow
{
scope(failure) return E_FAIL;
code_that_might_throw_here();
}
//----
So I think the behavior is correct. Maybe just not intuitive at first, or not correctly documented.
Comment #4 by shammah.chancellor — 2013-11-25T13:27:36Z
I understand what's happening, but I don't think scope(failure) should ever be used in this way. It's not what it was originally intended for, and can hide other scope(failures) without a compiler error being generated.. That's why I submitted the bug.
Comment #5 by shammah.chancellor — 2013-11-25T13:30:08Z
Also, see this -- scope(failure) unintentionally hiding an Error!
import std.stdio;
void someFunc()
{
scope(failure) { writeln("What?");} // <-- NEVER EXECUTED?!
scope(failure) {
writeln("Failed in someFunc()");
return;
}
try{
assert(0, "Hrm?");
} catch(Exception e) {
writefln("Exception!");
}
}
void main() {
try {
someFunc();
writeln("Yay, someFunc() is nothrow");
} catch(Exception e) {
writeln("An exception in main!");
}
}
Comment #6 by k.hara.pg — 2014-10-06T13:01:19Z
(In reply to Shammah Chancellor from comment #0)
> It was brought to my attention that scope(failure) can prevent the bubbling
> of exceptions by returning from the failure statement. This is bad
> behavior as scope failures can unintentionally prevent other scope failures
> from occurring.
> scope(failure) { writeln("What?");} // <-- NEVER EXECUTED?!
> scope(failure) {
scope(failure) is reached when an exception is thrown. In other words, it is on the "exceptional code path". And in scope(failure), you can go back to the regular code path by using return statement, and that's exactly what you doing there for error handling.
So, the outer scope(failure) is never reached. There's no bug.
Therefore I close this issue as resolved invalid.
---
However, as you can see, the outer scope(failure) is not reachable, but current dmd does not warn it even if you specify -w switch.
For that, I opened an enhancement issue 13575.