digitalmars.D - Proposal: "void f() { return 7; }" should be illegal
- Don <nospam nospam.com> Sep 29 2009
- bearophile <bearophileHUGS lycos.com> Sep 29 2009
- Jason House <jason.james.house gmail.com> Sep 29 2009
- Ary Borenszweig <ary esperanto.org.ar> Sep 29 2009
- grauzone <none example.net> Sep 29 2009
- Michel Fortin <michel.fortin michelf.com> Sep 29 2009
- "Denis Koroskin" <2korden gmail.com> Sep 29 2009
- Justin Johansson <procode adam-dott-com.au> Sep 29 2009
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Sep 29 2009
In the docs for "return statement" in statement.html it says:
---
ReturnStatement:
return;
return Expression ;
Expression is allowed even if the function specifies a void return type.
The Expression will be evaluated, but nothing will be returned.
----
This makes sense for things we definitely want to allow, such as:
void foo() { return bar(); }
where bar() is another void function. But as currently implemented, it
also allows bug-prone code. Here's an example from std.utf in Phobos2:
// BUG: should return size_t, not void!
void encode(wchar[2] buf, dchar c){
if (c <= 0xFFFF)
return 1;
return 2;
}
I think that instead, inside a void function, return expression; should
be the same as: { expression; return; }, ie, like any other expression
statement, it should be required to have side-effects. I found while
patching the ICE bug 3344 that this is happening because the expression
never gets the semantic pass run on it.
In DMD, in statement.c.
Statement *ReturnStatement::semantic(Scope *sc)
=====
/* Replace:
* return exp;
* with:
* exp; return;
*/
Statement *s = new ExpStatement(loc, exp);
+ s->semantic(sc);
=====
After making this change, it showed up that bug in Phobos.
I'm not sure if the current behaviour is intended, or is a bug. It
certainly looks unhelpful, unexpected, and bug-prone to me. As well as
the one-line compiler patch, I suggest the following change in the spec:
-The Expression will be evaluated, but nothing will be returned.
+The Expression will be evaluated as an ExpressionStatement, but nothing
will be returned.
Or is there something desirable about the existing behaviour which I
have missed?
Sep 29 2009
Don:In the docs for "return statement" in statement.html it says: --- ReturnStatement: return; return Expression ; Expression is allowed even if the function specifies a void return type. The Expression will be evaluated, but nothing will be returned.
I agree that making the language a little more strict in such regards is better.This makes sense for things we definitely want to allow, such as: void foo() { return bar(); } where bar() is another void function.
If bar() is a void function then "return bar();" looks like a bug. Why do you want to allow such semantically wrong situation? Bye, bearophile
Sep 29 2009
bearophile Wrote:Don:In the docs for "return statement" in statement.html it says: --- ReturnStatement: return; return Expression ; Expression is allowed even if the function specifies a void return type. The Expression will be evaluated, but nothing will be returned.
I agree that making the language a little more strict in such regards is better.This makes sense for things we definitely want to allow, such as: void foo() { return bar(); } where bar() is another void function.
If bar() is a void function then "return bar();" looks like a bug. Why do you want to allow such semantically wrong situation? Bye, bearophile
I believe the argument is to allow templated code to gracefully handle a void return type without special cases. It doesn't quite work since void is not a valid type for intermediate variables (leads to increased code duplication)
Sep 29 2009
Jason House wrote:bearophile Wrote:Don:In the docs for "return statement" in statement.html it says: --- ReturnStatement: return; return Expression ; Expression is allowed even if the function specifies a void return type. The Expression will be evaluated, but nothing will be returned.
This makes sense for things we definitely want to allow, such as: void foo() { return bar(); } where bar() is another void function.
Bye, bearophile
I believe the argument is to allow templated code to gracefully handle a void return type without special cases.
Well maybe the change could be made only to functions that are not templated.
Sep 29 2009
Denis Koroskin wrote:Unfortunately, you still have to special-case void type in a lot of cases. Here are just 2 examples:
And that's why there were ideas to allow declaring void variables. IMHO these void variables should allow all common operations on normal variables (assignment, passing as function parameter, taking address, dereferencing, void.init), and the compilation of those should simply result in no code.RetType doSomething(Args, RetType)(Args args, RetType retType) { RetType result = callSomeDelegate(args); // doesn't work for 'void' addLogEntry("bla-bla-bla"); return result; } class Test(T) { T foo(T t) { ... } T bar() { ... } T test() { return bar(foo()); // works for all types but 'void' } }
Sep 29 2009
On 2009-09-29 07:23:54 -0400, bearophile <bearophileHUGS lycos.com> said:This makes sense for things we definitely want to allow, such as: void foo() { return bar(); } where bar() is another void function.
If bar() is a void function then "return bar();" looks like a bug. Why do you want to allow such semantically wrong situation?
It's handy in generic code because you don't need to special-case for void: R foo(R, A...)(A a) { return bar(a); } That said, returning something other than void from a void function is senseless. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Sep 29 2009
On Tue, 29 Sep 2009 15:43:55 +0400, Jason House <jason.james.house gmail.com> wrote:bearophile Wrote:Don:In the docs for "return statement" in statement.html it says: --- ReturnStatement: return; return Expression ; Expression is allowed even if the function specifies a void return
The Expression will be evaluated, but nothing will be returned.
I agree that making the language a little more strict in such regards is better.This makes sense for things we definitely want to allow, such as: void foo() { return bar(); } where bar() is another void function.
If bar() is a void function then "return bar();" looks like a bug. Why do you want to allow such semantically wrong situation? Bye, bearophile
I believe the argument is to allow templated code to gracefully handle a void return type without special cases. It doesn't quite work since void is not a valid type for intermediate variables (leads to increased code duplication)
Unfortunately, you still have to special-case void type in a lot of cases. Here are just 2 examples: RetType doSomething(Args, RetType)(Args args, RetType retType) { RetType result = callSomeDelegate(args); // doesn't work for 'void' addLogEntry("bla-bla-bla"); return result; } class Test(T) { T foo(T t) { ... } T bar() { ... } T test() { return bar(foo()); // works for all types but 'void' } }
Sep 29 2009
Don Wrote:In the docs for "return statement" in statement.html it says: --- ReturnStatement: return; return Expression ; Expression is allowed even if the function specifies a void return type. The Expression will be evaluated, but nothing will be returned. ---- This makes sense for things we definitely want to allow, such as: void foo() { return bar(); } where bar() is another void function. But as currently implemented, it also allows bug-prone code. Here's an example from std.utf in Phobos2: // BUG: should return size_t, not void! void encode(wchar[2] buf, dchar c){ if (c <= 0xFFFF) return 1; return 2; } I think that instead, inside a void function, return expression; should be the same as: { expression; return; }, ie, like any other expression statement, it should be required to have side-effects. I found while patching the ICE bug 3344 that this is happening because the expression never gets the semantic pass run on it. In DMD, in statement.c. Statement *ReturnStatement::semantic(Scope *sc) ===== /* Replace: * return exp; * with: * exp; return; */ Statement *s = new ExpStatement(loc, exp); + s->semantic(sc); ===== After making this change, it showed up that bug in Phobos. I'm not sure if the current behaviour is intended, or is a bug. It certainly looks unhelpful, unexpected, and bug-prone to me. As well as the one-line compiler patch, I suggest the following change in the spec: -The Expression will be evaluated, but nothing will be returned. +The Expression will be evaluated as an ExpressionStatement, but nothing will be returned. Or is there something desirable about the existing behaviour which I have missed?
How about making a judgement based upon consistency & (co/contra) variance with "type is" operator? Try this for size: if ( is( int: void)) { writefln( "IT IS"); } else { writefln( "IT ISN'T"); } if ( is( void: int)) { writefln( "IT IS"); } else { writefln( "IT ISN'T"); } Therein either lies the answer, or proves that the type system is broken. Fan, do you have a comment about Unit type in Scala?
Sep 29 2009
Don wrote:In the docs for "return statement" in statement.html it says: --- ReturnStatement: return; return Expression ; Expression is allowed even if the function specifies a void return type. The Expression will be evaluated, but nothing will be returned. ---- This makes sense for things we definitely want to allow, such as: void foo() { return bar(); } where bar() is another void function. But as currently implemented, it also allows bug-prone code. Here's an example from std.utf in Phobos2: // BUG: should return size_t, not void! void encode(wchar[2] buf, dchar c){ if (c <= 0xFFFF) return 1; return 2; } I think that instead, inside a void function, return expression; should be the same as: { expression; return; }, ie, like any other expression statement, it should be required to have side-effects. I found while patching the ICE bug 3344 that this is happening because the expression never gets the semantic pass run on it. In DMD, in statement.c. Statement *ReturnStatement::semantic(Scope *sc) ===== /* Replace: * return exp; * with: * exp; return; */ Statement *s = new ExpStatement(loc, exp); + s->semantic(sc); ===== After making this change, it showed up that bug in Phobos. I'm not sure if the current behaviour is intended, or is a bug. It certainly looks unhelpful, unexpected, and bug-prone to me. As well as the one-line compiler patch, I suggest the following change in the spec: -The Expression will be evaluated, but nothing will be returned. +The Expression will be evaluated as an ExpressionStatement, but nothing will be returned. Or is there something desirable about the existing behaviour which I have missed?
I agree with your assessment. Andrei
Sep 29 2009









Ary Borenszweig <ary esperanto.org.ar> 