Re: Solution to "statement is not reachable" depending on template variables?
On Sunday, 18 June 2017 at 11:11:59 UTC, Johan Engelen wrote: On Sunday, 18 June 2017 at 09:56:50 UTC, Steven Schveighoffer wrote: On Sunday, 18 June 2017 at 09:28:57 UTC, Johan Engelen wrote: Reviving this thread to see whether anything has changed on the topic. If Timon gets static for each into the language, it can look a little better. Can you help me understand what you mean? How will it improve things? (static foreach would disable the "statement not reachable" analysis?) -Johan On my phone so can't be too detailed, but you could do: static foreach(i; 0..seq.length+1) static if(seq.length == i) return true; else static if(is(seq[i] == bool)) return false; Maybe looks a little better than the first workaround. -Steve
Re: Solution to "statement is not reachable" depending on template variables?
On Sunday, 18 June 2017 at 11:11:59 UTC, Johan Engelen wrote: On Sunday, 18 June 2017 at 09:56:50 UTC, Steven Schveighoffer wrote: On Sunday, 18 June 2017 at 09:28:57 UTC, Johan Engelen wrote: Reviving this thread to see whether anything has changed on the topic. If Timon gets static for each into the language, it can look a little better. Can you help me understand what you mean? How will it improve things? (static foreach would disable the "statement not reachable" analysis?) The new static foreach is AFAIK supposed to execute the loop instead of unrolling it, i.e. the expansion of --- foreach (i, U; T) { static if (is(U == bool)) { return false; } } return true; --- to --- static if (is(U1 == bool)) { return false; } static if (is(U2 == bool)) { return false; } ... return true; --- , which triggers that "statement is not reachable" if at least one of U1,U2,... = T is bool, will not occur if you instead use `static foreach (i, U; T)`.
Re: Solution to "statement is not reachable" depending on template variables?
On Sunday, 18 June 2017 at 09:56:50 UTC, Steven Schveighoffer wrote: On Sunday, 18 June 2017 at 09:28:57 UTC, Johan Engelen wrote: Reviving this thread to see whether anything has changed on the topic. If Timon gets static for each into the language, it can look a little better. Can you help me understand what you mean? How will it improve things? (static foreach would disable the "statement not reachable" analysis?) -Johan
Re: Solution to "statement is not reachable" depending on template variables?
On Sunday, 18 June 2017 at 09:28:57 UTC, Johan Engelen wrote: Reviving this thread to see whether anything has changed on the topic. If Timon gets static for each into the language, it can look a little better. -Steve
Re: Solution to "statement is not reachable" depending on template variables?
Reviving this thread to see whether anything has changed on the topic. I now have this monster: ``` struct FMT { // has immutable members. FMT cannot be assigned to. } FMT monsterThatCompilerAccepts(T)(){ alias TP = Tuple!(__traits(getAttributes, T)); foreach(i, att; TP){ static if( ... ) { return FMT( ... ); } // Make sure we return a default value in the last iteration. // Prevents "statement not reachable" warning when placed here instead of outside the foreach. else static if (i + 1 == TP.length) { return FMT( ... ); } } static if (TP.length == 0) { return FMT( ... ); } } FMT codeThatIsUnderstandableButNotAccepted(T)(){ alias TP = Tuple!(__traits(getAttributes, T)); foreach(i, att; TP){ static if( ... ) { return FMT( ... ); } } return FMT( ... ); } ``` Thanks, Johan
Re: Solution to "statement is not reachable" depending on template variables?
On Friday, 1 April 2016 at 01:21:32 UTC, Walter Bright wrote: On 3/16/2016 4:18 AM, Johan Engelen wrote: I've found discussions, but not an actual "recommended" solution for the problem of "statement is not reachable" warnings in templates with early returns, e.g.: ``` bool nobool(T...)() { foreach (i, U; T) { static if (is(U == bool)) { return false; } } return true; // emits "Warning: statement is not reachable" } bool nobool(T...)() { bool result = true; foreach (i, U; T) { static if (is(U == bool)) { result = false; break; } else { ... } } return result; // emits "Warning: statement is not reachable" } Note that the optimizer will remove the dead loads. Actually, I would expect every call of this fuction to be replaced by a boolean constant, since the result depends only on compile-time information. What happened to "obvious code should be correct"? Can we try to find a solution that doesn't look like a hack? I don't think that we should ask users of the language to uglify their code just to workaround a deficiency in the compiler. Instead, we should improve the lowering of the static foreach construct so the information that it is syntactically a loop is preserved after loop unrolling.
Re: Solution to "statement is not reachable" depending on template variables?
On Friday, 1 April 2016 at 01:21:32 UTC, Walter Bright wrote: On 3/16/2016 4:18 AM, Johan Engelen wrote: I've found discussions, but not an actual "recommended" solution for the problem of "statement is not reachable" warnings in templates with early returns, e.g.: ``` bool nobool(T...)() { foreach (i, U; T) { static if (is(U == bool)) { return false; } } return true; // emits "Warning: statement is not reachable" } bool nobool(T...)() { bool result = true; foreach (i, U; T) { static if (is(U == bool)) { result = false; break; } else { ... } } return result; // emits "Warning: statement is not reachable" } As you can see from my first post, that is the solution I used first (without the "break;" addition), but it works until... Note that the optimizer will remove the dead loads. ... until someone adds a (imho useful) diagnostic of dead stores/loads. :-) In that case, I guess inverting all bools and then inverting the return value at the end will work (using default initialization of result); but this is not possible in a slightly more complicated case with non-bool return types. In another piece of code, the return type is a struct with an immutable member. That's when I gave up on working around the warning and just disabled it. Simplified, something like this: struct IMM { immutable bool result; } IMM immut(T...)() { IMM retval = IMM(true); foreach (i, U; T) { static if (is(U == bool)) { retval = IMM(false); // "Error: cannot modify struct retval IMM with immutable member". } } return retval; }
Re: Solution to "statement is not reachable" depending on template variables?
On 3/16/2016 4:18 AM, Johan Engelen wrote: I've found discussions, but not an actual "recommended" solution for the problem of "statement is not reachable" warnings in templates with early returns, e.g.: ``` bool nobool(T...)() { foreach (i, U; T) { static if (is(U == bool)) { return false; } } return true; // emits "Warning: statement is not reachable" } bool nobool(T...)() { bool result = true; foreach (i, U; T) { static if (is(U == bool)) { result = false; break; } else { ... } } return result; // emits "Warning: statement is not reachable" } Note that the optimizer will remove the dead loads.
Solution to "statement is not reachable" depending on template variables?
Hi all, I've found discussions, but not an actual "recommended" solution for the problem of "statement is not reachable" warnings in templates with early returns, e.g.: ``` bool nobool(T...)() { foreach (i, U; T) { static if (is(U == bool)) { return false; } } return true; // emits "Warning: statement is not reachable" } bool nobool_nowarning(T...)() { bool retval = true; foreach (i, U; T) { static if (is(U == bool)) { retval = false; } } return retval; } void main() { static assert ( nobool_nowarning!(int,bool)() == false ); static assert ( nobool_nowarning!(int,int)() == true ); static assert ( nobool!(int,bool)() == false ); static assert ( nobool!(int,int)() == true ); } ``` (I have heavily simplified the real-world code, please don't discuss alternative solutions to the "is(U==bool)" in particular. For sake of argument, assume that the predicate is a complicated beast.) The `nobool` template prevents compilation with `-w`. Is `nobool_nowarning`, with the early return eradicated, the only acceptable solution? (with the hope that there will not be a "dead store" warning in the future...) What if early returns cannot be avoided? Thanks, Johan
Re: Solution to "statement is not reachable" depending on template variables?
On 3/16/16 7:18 AM, Johan Engelen wrote: Hi all, I've found discussions, but not an actual "recommended" solution for the problem of "statement is not reachable" warnings in templates with early returns, e.g.: ``` bool nobool(T...)() { foreach (i, U; T) { static if (is(U == bool)) { return false; } } return true; // emits "Warning: statement is not reachable" } Instead of foreach, you could use recursive mechanism. Not ideal, but it would work. Another possibility: foreach(i, U; T) { static if(is(U == bool)) { return false; } else static if(i + 1 == T.length) { return true; } } -Steve
Re: Solution to "statement is not reachable" depending on template variables?
On 3/16/16 9:48 PM, tsbockman wrote: On Wednesday, 16 March 2016 at 11:22:02 UTC, rikki cattermole wrote: Change those static if's to just plain old ifs. This only works (sometimes) because D's value range propagation doesn't understand comparisons or normal if statements very well. This will hopefully be fixed sooner or later: https://github.com/D-Programming-Language/dmd/pull/1913 https://github.com/D-Programming-Language/dmd/pull/5229 The only future-proof way to fix the "statement is not reachable" warning, is to guard the potentially unreachable code with a `static if` whose predicate precisely describes the circumstances in which it becomes unreachable... Which itself is a terrible solution that doesn't scale well at all to complex generic code and violates the "DRY" principle. We really ought to just remove the warning. It just doesn't mesh well with D's super-powered meta-programming features. Yes. I agree. The way I look at it is that the code *is* reached in some cases, so it should compile (and just remove that section in that instance). IMO any time a template value is used for branching, it should turn that warning off. -Steve
Re: Solution to "statement is not reachable" depending on template variables?
On Thursday, 17 March 2016 at 17:12:07 UTC, Steven Schveighoffer wrote: Yes. I agree. The way I look at it is that the code *is* reached in some cases, so it should compile (and just remove that section in that instance). IMO any time a template value is used for branching, it should turn that warning off. -Steve That's what I think it should do, also. However, when we discussed it before, Daniel Murphy pretty much told me there is no practical way to actually implement that behavior in the compiler. So, the next best thing is to just remove the warning entirely.
Re: Solution to "statement is not reachable" depending on template variables?
On Wednesday, 16 March 2016 at 11:18:36 UTC, Johan Engelen wrote: Hi all, I've found discussions, but not an actual "recommended" solution for the problem of "statement is not reachable" warnings in templates with early returns, e.g.: ``` bool nobool(T...)() { foreach (i, U; T) { static if (is(U == bool)) { return false; } } return true; // emits "Warning: statement is not reachable" } [...] On Wednesday, 16 March 2016 at 11:18:36 UTC, Johan Engelen wrote: import std.meta; template isBool(U)() = is(U == bool); static if (!allSatisfy!(isBool, T)) { return true; // no longer emits a warning } Something like this should work.
Re: Solution to "statement is not reachable" depending on template variables?
On Wednesday, 16 March 2016 at 11:47:35 UTC, QAston wrote: import std.meta; template isBool(U)() = is(U == bool); static if (!allSatisfy!(isBool, T)) { return true; // no longer emits a warning } Something like this should work. Thanks, but: On Wednesday, 16 March 2016 at 11:18:36 UTC, Johan Engelen wrote: (I have heavily simplified the real-world code, please don't discuss alternative solutions to the "is(U==bool)" in particular. For sake of argument, assume that the predicate is a complicated beast.)
Re: Solution to "statement is not reachable" depending on template variables?
On 17/03/16 5:05 AM, Johan Engelen wrote: On Wednesday, 16 March 2016 at 11:22:02 UTC, rikki cattermole wrote: Change those static if's to just plain old ifs. But then this wouldn't compile, would it? ``` static if(__traits(compiles, __traits(getMember, a, "b"))) { return a.b; } ``` (real code, I am not making this up) Hmm no. If that's in a foreach as well, you'll need to solve it some other way. --- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus
Re: Solution to "statement is not reachable" depending on template variables?
On Wednesday, 16 March 2016 at 17:08:20 UTC, Johan Engelen wrote: On Wednesday, 16 March 2016 at 11:47:35 UTC, QAston wrote: import std.meta; template isBool(U)() = is(U == bool); static if (!allSatisfy!(isBool, T)) { return true; // no longer emits a warning } Something like this should work. Thanks, but: On Wednesday, 16 March 2016 at 11:18:36 UTC, Johan Engelen wrote: (I have heavily simplified the real-world code, please don't discuss alternative solutions to the "is(U==bool)" in particular. For sake of argument, assume that the predicate is a complicated beast.) This method will work regarless of the predicate, just check if the predicate isn't matched for the whole array using allSatisfy/anySatisfy.
Re: Solution to "statement is not reachable" depending on template variables?
On Wednesday, 16 March 2016 at 17:34:13 UTC, Steven Schveighoffer wrote: On 3/16/16 7:18 AM, Johan Engelen wrote: Hi all, I've found discussions, but not an actual "recommended" solution for the problem of "statement is not reachable" warnings in templates with early returns, e.g.: ``` bool nobool(T...)() { foreach (i, U; T) { static if (is(U == bool)) { return false; } } return true; // emits "Warning: statement is not reachable" } Instead of foreach, you could use recursive mechanism. Not ideal, but it would work. Another possibility: foreach(i, U; T) { static if(is(U == bool)) { return false; } else static if(i + 1 == T.length) { return true; } } I like your second solution, it's clever :)
Re: Solution to "statement is not reachable" depending on template variables?
On Wednesday, 16 March 2016 at 11:22:02 UTC, rikki cattermole wrote: Change those static if's to just plain old ifs. This only works (sometimes) because D's value range propagation doesn't understand comparisons or normal if statements very well. This will hopefully be fixed sooner or later: https://github.com/D-Programming-Language/dmd/pull/1913 https://github.com/D-Programming-Language/dmd/pull/5229 The only future-proof way to fix the "statement is not reachable" warning, is to guard the potentially unreachable code with a `static if` whose predicate precisely describes the circumstances in which it becomes unreachable... ...Which itself is a terrible solution that doesn't scale well at all to complex generic code and violates the "DRY" principle. We really ought to just remove the warning. It just doesn't mesh well with D's super-powered meta-programming features.
Re: Solution to "statement is not reachable" depending on template variables?
On 16/03/16 11:18 PM, Johan Engelen wrote: Hi all, I've found discussions, but not an actual "recommended" solution for the problem of "statement is not reachable" warnings in templates with early returns, e.g.: ``` bool nobool(T...)() { foreach (i, U; T) { static if (is(U == bool)) { return false; } } return true; // emits "Warning: statement is not reachable" } bool nobool_nowarning(T...)() { bool retval = true; foreach (i, U; T) { static if (is(U == bool)) { retval = false; } } return retval; } void main() { static assert ( nobool_nowarning!(int,bool)() == false ); static assert ( nobool_nowarning!(int,int)() == true ); static assert ( nobool!(int,bool)() == false ); static assert ( nobool!(int,int)() == true ); } ``` (I have heavily simplified the real-world code, please don't discuss alternative solutions to the "is(U==bool)" in particular. For sake of argument, assume that the predicate is a complicated beast.) The `nobool` template prevents compilation with `-w`. Is `nobool_nowarning`, with the early return eradicated, the only acceptable solution? (with the hope that there will not be a "dead store" warning in the future...) What if early returns cannot be avoided? Thanks, Johan Change those static if's to just plain old ifs. Imagine those foreach loops being unrolled and what that happens there isn't just one return there, imagine many many many of them and all of them valid. --- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus
Re: Solution to "statement is not reachable" depending on template variables?
On Wednesday, 16 March 2016 at 11:22:02 UTC, rikki cattermole wrote: Change those static if's to just plain old ifs. But then this wouldn't compile, would it? ``` static if(__traits(compiles, __traits(getMember, a, "b"))) { return a.b; } ``` (real code, I am not making this up) Imagine those foreach loops being unrolled and what that happens there isn't just one return there, imagine many many many of them and all of them valid. Yep :-) Perhaps the only solution is to be able to annotate the code to "shut up" DMD about it.
Re: Solution to "statement is not reachable" depending on template variables?
On Wednesday, 16 March 2016 at 11:18:36 UTC, Johan Engelen wrote: Hi all, I've found discussions, but not an actual "recommended" solution for the problem of "statement is not reachable" warnings in templates with early returns... "statement is not reachable" is fundamentally broken in D for generic code: https://issues.dlang.org/show_bug.cgi?id=14835 It's mostly not too big of a deal right now, only because the D front end's value range propagation capabilities are very weak. Lionello Lunesu made a pull request a while back that majorly improves VRP in D as a part of his efforts to fix DMD issue 259. I decided to port it to DDMD a few months ago, and in the process discovered that with decent VRP, issue 14835 becomes 10-100x worse. There was a forum discussion a while back as to what should be done about this, but unfortunately the conclusion was that it probably cannot really be fixed with any reasonable effort: http://forum.dlang.org/thread/bnzfuekewfguvnwdz...@forum.dlang.org As far as I can tell, the only reasonable way forward is to simply remove the warning entirely (or ban meaningful upgrades to VRP).