digitalmars.D - Proposal: "void f() { return 7; }" should be illegal
- Don (43/43) Sep 29 2009 In the docs for "return statement" in statement.html it says:
- bearophile (5/16) Sep 29 2009 If bar() is a void function then "return bar();" looks like a bug. Why d...
- Jason House (2/24) Sep 29 2009 I believe the argument is to allow templated code to gracefully handle a...
- Denis Koroskin (19/49) Sep 29 2009 Unfortunately, you still have to special-case void type in a lot of case...
- grauzone (6/25) Sep 29 2009 And that's why there were ideas to allow declaring void variables.
- Ary Borenszweig (3/27) Sep 29 2009 Well maybe the change could be made only to functions that are not
- Michel Fortin (12/18) Sep 29 2009 It's handy in generic code because you don't need to special-case for vo...
- Justin Johansson (18/70) Sep 29 2009 How about making a judgement based upon consistency & (co/contra) varian...
- Andrei Alexandrescu (3/55) Sep 29 2009 I agree with your assessment.
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: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)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
On Tue, 29 Sep 2009 15:43:55 +0400, Jason House <jason.james.house gmail.com> wrote:bearophile Wrote: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' } }Don: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)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 returntype.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
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
Jason House wrote:bearophile Wrote:Well maybe the change could be made only to functions that are not templated.Don:I believe the argument is to allow templated code to gracefully handle a void return type without special cases.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
On 2009-09-29 07:23:54 -0400, bearophile <bearophileHUGS lycos.com> said: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/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?
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