import std.stdio;
int foo(int i, int j) nothrow
{
return i + j;
}
int bar() nothrow
{
return 0;
}
void test() nothrow
{
int x = bar();
int y = foo(x, x);
writefln("%d, %d", x, y);
}
void main()
{
test();
}
Expected output:
test.d(13): Error: function test.test 'test' is nothrow yet writefln at test.d(17) may throw
Actual output:
test.d(13): Error: function test.test 'test' is nothrow yet may throw
Rising its severity because the feature is barely usable without appropriate error messages.
Comment #1 by issues.dlang — 2010-09-17T23:38:10Z
I'm not sure that I agree that this bug is "critical," since dmd works fine with this bug. It's just highly annoying. But as it is highly annoying, it would definitely be nice to have this fixed. If you're trying to make your code use nothrow as much as possible (which I would think would be ideal, just as you'd try and use const as much as possible), this bug really gets in the way. It's not fatal, but it sure is annoying.
Comment #2 by bearophile_hugs — 2010-09-19T17:46:06Z
This isn't a critical bug. There are FAR worse bugs in DMD that are rated as normal bugs.
Comment #3 by clugdbug — 2010-10-22T17:16:07Z
Created attachment 790
patch against svn 724
This is a big patch, but it's very simple. When checking for the return type of functions, the info about whether it is a nothrow function is passed as a parameter. If it throws from inside a nothrow function, it generates an error message.
Comment #4 by clugdbug — 2010-10-22T17:23:09Z
For the initial test case, the error messages are:
test.d(17): Error: writefln is not nothrow
test0.d(13): Error: function test0.test 'test' is nothrow yet may throw
Another example:
=======
import core.exception;
void foo() nothrow
{
try {
throw new Exception("xxx");
} catch(Exception e) {
auto z = new int;
throw e;
}
}
----
test.d(8): Error: 'new int' may throw OutOfMemoryError
test.d(9): Error: object.Exception is thrown but not caught
test.d(3): Error: function test0.foo 'foo' is nothrow yet may throw
Comment #5 by bugzilla — 2010-10-29T03:21:11Z
Out of memory errors should be allowed inside nothrow.
Also, I suspect it would be good to disallow:
try
{
...
}
catch (Exception e)
{
/* nothing here */
}
where all exceptions are swallowed and ignored. This kind of thing happens in Java to work around exception specifications, but I don't see a need for it here. Of course, there would still be ways to swallow & ignore (just put in a call to a do-nothing function), but such shouldn't be easy.
What do you think?
Comment #6 by issues.dlang — 2010-10-29T03:37:35Z
There are plenty of cases where you know that a function will never throw but it's not nothrow (perhaps because it can throw in other circumstances), and you're forced to catch the Exception anyway (probably because you're in a nothrow function). Personally, I use assert(0) for such cases.
As long as disallowing empty catch blocks is really for _empty_ catch blocks (or catch blocks with only a comment), I don't mind. But there are definitely cases where you want to eat an exception or where there should never be one but you have to have a try-catch anyway.
Comment #7 by clugdbug — 2010-10-29T05:30:34Z
(In reply to comment #5)
> Out of memory errors should be allowed inside nothrow.
Good. I think so too. That will make nothrow much more useful.
In the existing compiler, they are disallowed.
( void foo() nothrow { auto x = new int; } won't compile).
I just added error messages to specify why it was being disallowed.
It sounds as though the check for nothrow violations should be separated from the code which determines if a statement can throw. That is, for 'new' and for asm, we assume that it can throw. But, if it's in a nothrow function, we trust the programmer.
Then, what happens if an out of memory condition happens in a nothrow function? Is the program simply terminated?
>
> Also, I suspect it would be good to disallow:
>
> try
> {
> ...
> }
> catch (Exception e)
> {
> /* nothing here */
> }
>
> where all exceptions are swallowed and ignored. This kind of thing happens in
> Java to work around exception specifications, but I don't see a need for it
> here. Of course, there would still be ways to swallow & ignore (just put in a
> call to a do-nothing function), but such shouldn't be easy.
>
> What do you think?
Dunno. It's certainly bad style.
Comment #8 by bugzilla — 2010-10-29T10:29:39Z
(In reply to comment #7)
> In the existing compiler, they are disallowed.
That's a bug.
> ( void foo() nothrow { auto x = new int; } won't compile).
> I just added error messages to specify why it was being disallowed.
> It sounds as though the check for nothrow violations should be separated from
> the code which determines if a statement can throw. That is, for 'new' and for
> asm, we assume that it can throw. But, if it's in a nothrow function, we trust
> the programmer.
> Then, what happens if an out of memory condition happens in a nothrow function?
> Is the program simply terminated?
Yes.
Comment #9 by andrei — 2010-10-29T11:11:26Z
(In reply to comment #5)
> Out of memory errors should be allowed inside nothrow.
>
> Also, I suspect it would be good to disallow:
>
> try
> {
> ...
> }
> catch (Exception e)
> {
> /* nothing here */
> }
>
> where all exceptions are swallowed and ignored. This kind of thing happens in
> Java to work around exception specifications, but I don't see a need for it
> here. Of course, there would still be ways to swallow & ignore (just put in a
> call to a do-nothing function), but such shouldn't be easy.
>
> What do you think?
There are plenty of cases when you want to swallow exceptions, and it's highly unlikely that anyone would write such a pattern by mistake. So let's keep allowing it. At best, the compiler could protest that "e" is not being used and ask for a nameless catch.