digitalmars.D - Fixing the issue with "Statement unreachable"
- Steven Schveighoffer (68/68) Apr 26 2020 Is there a way we can fix this?
- drug (2/2) Apr 26 2020 Not fix, just an other way - instead of final `return false;` (not teste...
- Mathias LANG (11/19) Apr 26 2020 Personally when I can't find any satisfactory solution, I just
- Walter Bright (33/33) Apr 29 2020 I guessed at what was necessary to finish the example:
- Timon Gehr (28/30) Apr 30 2020 You need -W. -W also notices the dangling elses, the intended code is th...
- matheus (49/54) Apr 30 2020 True and by the way I minimized the code:
- Steven Schveighoffer (15/83) Apr 30 2020 Right, the first would still include the return false as generated code,...
- matheus (33/67) Apr 30 2020 Yes I got what you mean, and I would agree with that logic too,
- Steven Schveighoffer (30/93) Apr 30 2020 So what is happening is that the static if is literally including or
- Steven Schveighoffer (5/10) Apr 30 2020 I didn't even know that, I was just building phobos, which probably
Is there a way we can fix this? I have a situation with a large set of nested static ifs, coupled with returns based on runtime code: ----- static if(condA) { static if(condB) { static if(condC) if(funA()) return true; else static if(condD) if(funB()) return true; else if(funC()) return true; } else static if(condD) if(funD()) return true; else if(funE()) return true; } return false; ----- Now, I have a situation where I'm inserting a condition nested way down. And it always is going to return true: ---- static if(condA) { static if(condB) { static if(NEW_CONDITION) return true; else static if(condC) if(funA()) return true; else static if(condD) if(funB()) return true; else if(funC()) return true; } else static if(condD) if(funD()) return true; else if(funE()) return true; } return false; ---- Now, all of a sudden, the return false at the end is no good. If condA, condB, and NEW_CONDITION are true, the return false becomes a "Statement not reachable". I see 2 ways to fix this, and both are horrible. Way 1: I have a special static if before-hand that combines all the various conditions that get to that new branch, and then else everything else. e.g.: static if(condA && condB && NEW_CONDITION) return true; else { ... original code ... } Way 2: I move "return false" in all the other branches. I can refactor out some of them, but I need a lot, which is super-annoying. It bugs me that the compiler can't figure this out. Is there any way we can fix this? The "warning" is not really true -- the statement IS reachable in some instantiations. Personally, I'd rather not have the compiler complain about ANY unreachable statements than complain about ones that are actually reachable. If it determines it's not reachable, just don't put it in the binary. Would there be a way to say "if this part of the code is reachable, then include the following"? (NOTE: I know I could switch all the "return true" to return the result of the functions, but the real code is more complex and not simple boolean calls) -Steve
Apr 26 2020
Not fix, just an other way - instead of final `return false;` (not tested): static if(!condA || !condB || !NEW_CONDITION) return false;
Apr 26 2020
On Monday, 27 April 2020 at 03:59:57 UTC, Steven Schveighoffer wrote:Is there a way we can fix this? [...] Would there be a way to say "if this part of the code is reachable, then include the following"? (NOTE: I know I could switch all the "return true" to return the result of the functions, but the real code is more complex and not simple boolean calls) -StevePersonally when I can't find any satisfactory solution, I just add `bool hack` at the top and an `if (!hack)`. The backend / inliner might be smart enough to optimize it, but it's enough to shut the frontend up. This is essentially https://issues.dlang.org/show_bug.cgi?id=14835 . As you can see, Andrei proposed to insert an `else` if there's a static if. I'm personally not fan of this, I just think we should fix DMD frontend to stop emitting useless warnings.
Apr 26 2020
I guessed at what was necessary to finish the example: ------------- bool test() { static if(condA) { static if(condB) { static if(NEW_CONDITION) return true; else static if(condC) if(funA()) return true; else static if(condD) if(funB()) return true; else if(funC()) return true; } else static if(condD) if(funD()) return true; else if(funE()) return true; } return false; } enum bool condA = true, condB = true, condC = true, condD = true; enum NEW_CONDITION = true; bool funA(); bool funB(); bool funC(); bool funD(); bool funE(); ---------------------- which compiles without error. Evidently, your example must be different from this. Please post a complete example.
Apr 29 2020
On 30.04.20 08:00, Walter Bright wrote:Evidently, your example must be different from this. Please post a complete example.You need -W. -W also notices the dangling elses, the intended code is this: bool test(){ static if(condA){ static if(condB){ static if(NEW_CONDITION) return true; else static if(condC){ if(funA()) return true; }else static if(condD) { if(funB()) return true; }else{ if(funC()) return true; } }else static if(condD){ if(funD()) return true; }else{ if(funE()) return true; } } return false; // Warning: statement is not reachable } enum bool condA = true, condB = true, condC = true, condD = true; enum NEW_CONDITION = true; bool funA(); bool funB(); bool funC(); bool funD(); bool funE();
Apr 30 2020
On Thursday, 30 April 2020 at 09:10:16 UTC, Timon Gehr wrote:On 30.04.20 08:00, Walter Bright wrote:True and by the way I minimized the code: // THIS WORKS - https://d.godbolt.org/z/3v-gW2: import std.stdio; bool test(){ static if(cond){ if(func()){return true;} } return false; } enum bool cond = true; bool func(); void main(string[ ] args) { writeln(test()); } // WHILE BELOW GIVES THE ERROR: https://d.godbolt.org/z/8rNdjJ import std.stdio; bool test(){ static if(cond){ return true; } return false; } enum bool cond = true; bool func(); void main(string[ ] args) { writeln(test()); } As you can see, when you explicitly define a return inside a static if, the compiler emits the warning. I think this is a wrong behavior and the warning only should be emitted if the code above had an "else", like for example: // https://d.godbolt.org/z/fgY34m import std.stdio; bool test(){ static if(cond){ return true; }else{ return false; } return false; } enum bool cond = true; bool func(); void main(string[ ] args) { writeln(test()); } In the above the warning makes sense. Matheus.Evidently, your example must be different from this. Please post a complete example.You need -W. -W also notices the dangling elses, the intended code is this:
Apr 30 2020
On 4/30/20 10:02 AM, matheus wrote:On Thursday, 30 April 2020 at 09:10:16 UTC, Timon Gehr wrote:Right, the first would still include the return false as generated code, this is not in dispute. And in fact, in your case, I would say the error is legitimate (that line is not reachable). But in the case of a template where the condition is passed in, the line is reachable if the condition is one way. However, there are other reasons why this might be "reachable" in other cases. For example, you could have: version(abc) enum cond = false; else enum cond = true; which means that if you *compile* it a certain way, then it's reachable.On 30.04.20 08:00, Walter Bright wrote:True and by the way I minimized the code: // THIS WORKS - https://d.godbolt.org/z/3v-gW2: import std.stdio; bool test(){ static if(cond){ if(func()){return true;} } return false; } enum bool cond = true; bool func(); void main(string[ ] args) { writeln(test()); } // WHILE BELOW GIVES THE ERROR: https://d.godbolt.org/z/8rNdjJ import std.stdio; bool test(){ static if(cond){ return true; } return false; } enum bool cond = true; bool func(); void main(string[ ] args) { writeln(test()); } As you can see, when you explicitly define a return inside a static if, the compiler emits the warning.Evidently, your example must be different from this. Please post a complete example.You need -W. -W also notices the dangling elses, the intended code is this:I think this is a wrong behavior and the warning only should be emitted if the code above had an "else", like for example: // https://d.godbolt.org/z/fgY34m import std.stdio; bool test(){ static if(cond){ return true; }else{ return false; } return false; } enum bool cond = true; bool func(); void main(string[ ] args) { writeln(test()); } In the above the warning makes sense.This makes a lot of sense, and probably is the way to go -Steve
Apr 30 2020
On Thursday, 30 April 2020 at 14:29:27 UTC, Steven Schveighoffer wrote:On 4/30/20 10:02 AM, matheus wrote:Yes I got what you mean, and I would agree with that logic too, except that while this gives a warning: bool test(){ static if(cond){ return true; } return false; } Just adding "else" to the code above will make it work normally: bool test(){ static if(cond){ return true; }else return false; } This is a bit weird for me, I really thought the compiler would be smart enough to handle this. If I was doing a benchmark between functions I'd like to do: void func(){ static if(TryDoSomethingA){ doSomethingA(); return; } doSomethingB(); } But to make this work I'll need to add an extra "else", which I hate and I always try to avoid in my code. Well my background is C and maybe there is a reason for the use of "else" with "static if".... // WHILE BELOW GIVES THE ERROR: https://d.godbolt.org/z/8rNdjJ import std.stdio; bool test(){ static if(cond){ return true; } return false; } enum bool cond = true; bool func(); void main(string[ ] args) { writeln(test()); } As you can see, when you explicitly define a return inside a static if, the compiler emits the warning.Right, the first would still include the return false as generated code, this is not in dispute. And in fact, in your case, I would say the error is legitimate (that line is not reachable).But in the case of a template where the condition is passed in, the line is reachable if the condition is one way. However, there are other reasons why this might be "reachable" in other cases. For example, you could have: version(abc) enum cond = false; else enum cond = true; which means that if you *compile* it a certain way, then it's reachable.Exactly and I agree. Matheus.
Apr 30 2020
On 4/30/20 2:25 PM, matheus wrote:On Thursday, 30 April 2020 at 14:29:27 UTC, Steven Schveighoffer wrote:So what is happening is that the static if is literally including or trimming out the code based on the boolean. It's as if you wrote: bool test() { // static if(cond) { => included for cond == true return true; // } return false; } which the "linter" or whatever generates the warning looks at and says it's no good, because it looks like 2 sequential return statements. What it really should do is simply remove the second return and shut up ;)On 4/30/20 10:02 AM, matheus wrote:Yes I got what you mean, and I would agree with that logic too, except that while this gives a warning: bool test(){ static if(cond){ return true; } return false; } Just adding "else" to the code above will make it work normally: bool test(){ static if(cond){ return true; }else return false; } This is a bit weird for me, I really thought the compiler would be smart enough to handle this.... // WHILE BELOW GIVES THE ERROR: https://d.godbolt.org/z/8rNdjJ import std.stdio; bool test(){ static if(cond){ return true; } return false; } enum bool cond = true; bool func(); void main(string[ ] args) { writeln(test()); } As you can see, when you explicitly define a return inside a static if, the compiler emits the warning.Right, the first would still include the return false as generated code, this is not in dispute. And in fact, in your case, I would say the error is legitimate (that line is not reachable).If I was doing a benchmark between functions I'd like to do: void func(){ static if(TryDoSomethingA){ doSomethingA(); return; } doSomethingB(); } But to make this work I'll need to add an extra "else", which I hate and I always try to avoid in my code.There is one possibility, which is only valid for static conditionals: void func() { static if(cond) return; else: // note the colon return; // note the indentation } Basically, it's saying, do everything else in this scope, but don't make me indent. It could be a simple way to fix the problem. I think Andrei suggested this in the bug report quoted before. Essentially, the compiler could insert an else: whenever it encounters a static if without an else, where all paths exit the outer scope for that compilation. But the compiler should be smart enough to just not report errors in these cases.Well my background is C and maybe there is a reason for the use of "else" with "static if".Yes, if you consider the AST rewriting that static if does, it makes sense, because the linter doesn't know how the AST came about. -Steve
Apr 30 2020
On 4/30/20 5:10 AM, Timon Gehr wrote:On 30.04.20 08:00, Walter Bright wrote:I didn't even know that, I was just building phobos, which probably includes the -W. Thanks. -SteveEvidently, your example must be different from this. Please post a complete example.You need -W. -W also notices the dangling elses, the intended code is this:
Apr 30 2020