Bug 11461 – `Error`s are not thrown as `pure nothrow` functions are optimized out with "-O -release"

Status
RESOLVED
Resolution
WORKSFORME
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-11-07T00:15:14Z
Last change time
2021-11-16T09:48:30Z
Keywords
pull, wrong-code
Assigned to
No Owner
Creator
Denis Shelomovskii

Comments

Comment #0 by verylonglogin.reg — 2013-11-07T00:15:14Z
This program runs without errors if compiled with "-O -release" and `f` is strongly pure and `nothrow`: --- void f() pure nothrow { throw new Error(""); } void main() { f(); } --- So optimizer must not completely optimize out even `nothrow` strongly pure function calls as an `Error` still could be thrown or there could be a HLT instruction.
Comment #1 by code — 2013-11-14T18:36:52Z
Well, if a function has no side effect and does not produce a result or the result isn't used, there is no point in calling it. It's pretty harsh to demand that the compiler always calls such functions only to support the minor noreturn use-case.
Comment #2 by verylonglogin.reg — 2013-11-14T21:26:02Z
(In reply to comment #1) > Well, if a function has no side effect and does not produce a result or the > result isn't used, there is no point in calling it. It's pretty harsh to demand > that the compiler always calls such functions only to support the minor > noreturn use-case. Minor or no it is documented `pure` functions can throw and the compiler already consider `pure` but not `nothrow` functions as doing this (i.e. they aren't optimized out). So `nothrow` must be treated the same way as `nothrow` just means no recoverable `Exception`s are thrown. Breaking language changes are welcome but in a separate enhancement issue. Currently `onOutOfMemoryError` is no-op because of this and the issue should be fixed.
Comment #3 by code — 2013-11-15T00:09:19Z
Interesting btw, such a function will either never or always throw an Error.
Comment #4 by monarchdodra — 2013-11-15T01:23:58Z
(In reply to comment #2) > (In reply to comment #1) > > Well, if a function has no side effect and does not produce a result or the > > result isn't used, there is no point in calling it. It's pretty harsh to demand > > that the compiler always calls such functions only to support the minor > > noreturn use-case. > > Minor or no it is documented `pure` functions can throw and the compiler > already consider `pure` but not `nothrow` functions as doing this (i.e. they > aren't optimized out). So `nothrow` must be treated the same way as `nothrow` > just means no recoverable `Exception`s are thrown. Breaking language changes > are welcome but in a separate enhancement issue. Currently `onOutOfMemoryError` > is no-op because of this and the issue should be fixed. I don't know... an "Error" isn't really considered as "observable program behavior", is it? If a function is (either strongly or weakly) pure, takes no reference arguments, and is nothrow, then it calling it will not have observable side effect, and can (and IMO should) be optimized out. This can be workaround simply by forcing the function to look like it can have "observable side effects", as so: //---- void f(void* = null) pure nothrow { throw new Error(""); } void main() { f(); } //----
Comment #5 by code — 2013-11-15T01:35:56Z
(In reply to comment #3) > Interesting btw, such a function will either never or always throw an Error. The fix is fairly simple, we need a way to annotate noreturn functions.
Comment #6 by github-bugzilla — 2013-11-15T03:57:30Z
Comment #7 by github-bugzilla — 2013-11-15T10:33:56Z
Comment #8 by temtaime — 2013-11-15T10:38:43Z
Hi, guys. Maybe i'm too stupid, but how nothrow function can throw ?
Comment #9 by monarchdodra — 2013-11-15T11:53:06Z
(In reply to comment #8) > Hi, guys. > Maybe i'm too stupid, but how nothrow function can throw ? D defines both "Exception" and "Error", which derive from "Throwable". "Exception", is what you know from C++: The standard thing that gets thrown around to notify things like database/io problems: Things that "happen" and need to be dealt with. They unwind the stack, destroy things on the stack, etc... "Error" is an entire other beast: They are C++'s "assert" in more powerful: They represent a critical error of the program state: corruption, out of memory, failed assertions. They represent something you *cannot* recover from, and are telling you the program needs to halt. Unlike an "Exception", "Error" will blast through the call stack, bypassing destructors, bypassing "nothrow" function, bypassing "catch(Exception)"... They are not meant to happen general, and shouldn't be "handled" in the general sense of the term. So long story short, an Error can be thrown from a nothrow function, because an Error doesn't trigger stack cleanup, which means there is no need to generate _Exceptio_ handling code". => "nothrow" means "will not throw _Exceptions_". I'd link some references, but the best I know of is TDPL.
Comment #10 by temtaime — 2013-11-15T12:33:55Z
Clear. Thanks very much for explanation.
Comment #11 by r.sagitario — 2014-03-22T04:48:07Z
(In reply to comment #7) > Commit pushed to master at https://github.com/D-Programming-Language/druntime > > https://github.com/D-Programming-Language/druntime/commit/0422e58d1bd6c86063f73b9ca372e5e16afd64b0 > Add issue 11461 workaround. > > Issue URL: https://d.puremagic.com/issues/show_bug.cgi?id=11461 Any particular reason why "pure" isn't removed from the onOutOfMemoryError declaration in core.exception aswell? And for all the other error functions?
Comment #12 by bearophile_hugs — 2014-03-22T05:32:37Z
(In reply to comment #5) > (In reply to comment #3) > > Interesting btw, such a function will either never or always throw an Error. > > The fix is fairly simple, we need a way to annotate noreturn functions. On this there is no DIP and perhaps not even an enhancement request.
Comment #13 by monarchdodra — 2014-03-22T14:59:11Z
Maybe the problem can be worked around by making the function(s) *weakly* pure? (In reply to comment #11) > (In reply to comment #7) > > Commit pushed to master at https://github.com/D-Programming-Language/druntime > > > > https://github.com/D-Programming-Language/druntime/commit/0422e58d1bd6c86063f73b9ca372e5e16afd64b0 > > Add issue 11461 workaround. > > > > Issue URL: https://d.puremagic.com/issues/show_bug.cgi?id=11461 > > Any particular reason why "pure" isn't removed from the onOutOfMemoryError > declaration in core.exception aswell? And for all the other error functions? Instead of removing the "pure", which is a breaking change, since it would prevent pure functions from having an "onOutOfMemoryError", what about my suggestion for weak purity? void onOutOfMemoryError(void* dummy11461 = null) @trusted pure nothrow; or just: void onOutOfMemoryError(void* = null) @trusted pure nothrow; instead of void onOutOfMemoryError() @trusted /* pure dmd @@@BUG11461@@@ */ nothrow;
Comment #14 by r.sagitario — 2014-03-23T02:32:33Z
I agree, it seems the better workaround. Clever compilers might notice that the passed parameter introduces no sideeffects and might infer strong purity, though.
Comment #15 by r.sagitario — 2014-03-23T03:28:42Z
Comment #16 by github-bugzilla — 2014-03-23T18:11:42Z
Commit pushed to master at https://github.com/D-Programming-Language/druntime https://github.com/D-Programming-Language/druntime/commit/2a50ceabb436d150ee4e6bfff299def58bc9e92c Merge pull request #753 from rainers/workaround_bug11461 Workaround 11461: avoid strong purity inference by passing null pointer to onOutOfMemoryError
Comment #17 by naptimeentertainment — 2016-02-14T11:00:51Z
(In reply to bearophile_hugs from comment #12) > (In reply to comment #5) > > The fix is fairly simple, we need a way to annotate noreturn functions. > > On this there is no DIP and perhaps not even an enhancement request. I know this is off-topic, but I don't think it warrants a forum post... if someone thinks it does then I'll make one: I've never made a DIP before, but @noreturn is a feature that I care about, and there is still no DIP for @noreturn despite the fact that this issue is over two years old. I'm sure I could find the time to write a proposal or two for enhancements I really care about (I happen to have a knack for technical writing). 1. Can anyone (me) just create a DIP, or does there have to be some sort of approval or discussion first before I post it? 2. Is it required that there be a corresponding issue in the issue tracker for the problem addressed by the DIP? 3. Similarly, is it required that there be a corresponding link to a news group discussion (discussion, not announcement -- I know the announcement is required)? http://wiki.dlang.org/DIP1 made it seem like a discussion link is preferred but not required, but I just wanted to make sure. Thanks in advance >^,^<
Comment #18 by alphaglosined — 2016-02-14T11:07:49Z
(In reply to naptime from comment #17) You're more than welcome to create a DIP. Create a wiki page dedicated to the topic as close to the DIP structure as possible. We can sort out making it into a proper DIP later. Once you have something to show, post to the N.G. about it, from there its just a matter of iterating over it and making it usable.
Comment #19 by moonlightsentinel — 2021-11-16T09:48:30Z