Bug 3922 – Refuse returning nonvoid from void functions

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2010-03-10T05:02:00Z
Last change time
2012-01-18T18:44:18Z
Keywords
accepts-invalid, diagnostic
Assigned to
nobody
Creator
bearophile_hugs

Comments

Comment #0 by bearophile_hugs — 2010-03-10T05:02:48Z
This is a wrong program: void foo(int x) { return x; } void main() {} Currently dmd2 generates a bad error message: temp.d(2): Error: var has no effect in expression (x) A much better error message can be: temp.d(2): Error: return can't be used in a void function. Bad error messages like this one do waste my programming time.
Comment #1 by bearophile_hugs — 2010-03-28T06:34:11Z
This program: void foo() { return 0; } enum x = foo(); void main() {} With dmd 2.042 gives a wrong error message: test.d(2): Error: variable bug3.x voids have no value A better error message can be: test.d(1): Error: return statement not allowed in void functions.
Comment #2 by ibuclaw — 2010-08-21T04:47:59Z
*** Issue 4701 has been marked as a duplicate of this issue. ***
Comment #3 by bearophile_hugs — 2010-08-21T05:09:39Z
Those error messages I have suggested are wrong, because using return in a void function is OK: void foo() { return; } void main() {} It seems that this too is allowed: void foo() { return; } void bar() { return foo(); } void main() {} What's wrong is returning something that is not void from a void function. So a better error message is needed. So for this wrong code: void foo() { return 0; } void main() {} A possible message: temp.d(2): Error: a void function can return void only. Alternative: temp.d(2): Error: a void function can't return an int.
Comment #4 by kennytm — 2011-06-08T11:11:04Z
The error seems to be that, in a 'void' function, the statement return expr; is rewritten to { expr; return; } so e.g. the following should-be-wrong (?) code int a() { return 4; } void b() { return a(); } will compile successfully.
Comment #5 by kennytm — 2011-06-08T11:29:02Z
... indeed it is. // ReturnStatement::semantic if (exp && tbret->ty == Tvoid && !implicit0) { /* Replace: * return exp; * with: * exp; return; */ Statement *s = new ExpStatement(loc, exp); exp = NULL; s = s->semantic(sc); return new CompoundStatement(loc, s, this); } Perhaps there should be a check in 'exp' here to ensure its type is 'void'.
Comment #6 by bearophile_hugs — 2011-06-13T03:21:06Z
*** This issue has been marked as a duplicate of issue 3746 ***
Comment #7 by bearophile_hugs — 2011-06-14T05:18:56Z
Reopened as enhancement request after discussions in bug 3746. This is from the DMD 2.053 specs: http://www.digitalmars.com/d/2.0/statement.html#ReturnStatement Expression is allowed even if the function specifies a void return type. The Expression will be evaluated, but nothing will be returned. If the Expression has no side effects, and the return type is void, then it is illegal. So according to the D specs this code is illegal: pure int sqr(int x) { return x * x; } void main() { return sqr(10); } While this code is correct: int sqr(int x) { return x * x; } void main() { return sqr(10); } But I can't see this as correct, it's bug prone. I think it's better to turn into an error returning any nonvoid from a void function, regardless of side effects.
Comment #8 by hoganmeier — 2012-01-05T14:29:46Z
I totally agree, just like others: http://d.puremagic.com/issues/show_bug.cgi?id=3746#c12 This has to happen. Let's consider this a bug and not an enhancements.
Comment #9 by bearophile_hugs — 2012-01-05T15:36:21Z
The main real problem (returning a non void from a void function) is now fixed: https://github.com/D-Programming-Language/dmd/commit/c942d51c8b1103d5ce4c3dfc03ae77c07c687cd6 ----------------- DMD 2.058head accepts code like this: void foo() { return; } void main() { return foo(); } This code is formally correct, because no real value is ignored. I don't like such code a lot because that code looks like the intent of the programmer is to return something, while this is not true. Maybe allowing this is useful for generic code, I don't know. I'd like to see examples of this usefulness in real code. (But this discussion looks a bit different from the main issue that is now fixed, so maybe this should be moved to a new different Bugzilla issue).
Comment #10 by timon.gehr — 2012-01-05T16:40:47Z
This is required for forwarding and cannot change. auto foo(T...)(T args){return bar(args);}
Comment #11 by bearophile_hugs — 2012-01-05T16:54:55Z
(In reply to comment #10) > This is required for forwarding and cannot change. > > auto foo(T...)(T args){return bar(args);} Thank you for your answer. If you are right and it can't change, then this issue should be closed.
Comment #12 by hoganmeier — 2012-01-06T04:59:49Z
(In reply to comment #10) > This is required for forwarding and cannot change. > > auto foo(T...)(T args){return bar(args);} Well couldn't this special case be checked? Accidentally turning the return type into void or forgetting to change the type from void after you added a return x; is much more common than such code imho. Also should a function returning something or not really depend on argument types?
Comment #13 by timon.gehr — 2012-01-06T06:28:39Z
(In reply to comment #12) > (In reply to comment #10) > > This is required for forwarding and cannot change. > > > > auto foo(T...)(T args){return bar(args);} > > Well couldn't this special case be checked? > Accidentally turning the return type into void Who on earth accidentally changes a function's return type? Also, if the function does not actually return void, a compile error results. > or forgetting to change the type > from void after you added a return x; is much more common than such code imho. That will give a compile error already. (unless x is a property function returning void) > Also should a function returning something or not really depend on argument > types? You realize that it is already disallowed to return non-void from a function returning void? The only case that is allowed and should stay allowed is something like this: void bar(){...} void foo(){return bar();}
Comment #14 by yebblies — 2012-01-18T18:44:18Z
As far as I can tell, this bug has been fixed with issue 3746 and issue 5399. Returning a value from a void function is only allowed when the value evaluates to void, preventing the value from being lost accidentally.