Bug 11574 – Improper behavior of scope(failure)

Status
RESOLVED
Resolution
INVALID
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-11-21T18:40:00Z
Last change time
2014-10-06T13:01:19Z
Assigned to
nobody
Creator
shammah.chancellor

Attachments

IDFilenameSummaryContent-TypeSize
1293foo.dShows how scope(failure) return's can prevent proper exception bubbling.application/octet-stream408

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.