Jump to page: 1 2 3
Thread overview
Solution to "statement is not reachable" depending on template variables?
Mar 16, 2016
Johan Engelen
Mar 16, 2016
rikki cattermole
Mar 16, 2016
Johan Engelen
Mar 17, 2016
rikki cattermole
Mar 17, 2016
tsbockman
Mar 17, 2016
tsbockman
Mar 16, 2016
QAston
Mar 16, 2016
Johan Engelen
Mar 19, 2016
QAston
Mar 16, 2016
Johan Engelen
Mar 17, 2016
tsbockman
Apr 01, 2016
Walter Bright
Apr 01, 2016
Johan Engelen
Apr 01, 2016
ZombineDev
Jun 18, 2017
Johan Engelen
Jun 18, 2017
Johan Engelen
Jun 18, 2017
Moritz Maxeiner
March 16, 2016
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

March 16, 2016
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

March 16, 2016
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.
March 16, 2016
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.
March 16, 2016
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.)

March 16, 2016
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
March 16, 2016
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 :)


March 17, 2016
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/bnzfuekewfguvnwdznfk@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).
March 17, 2016
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.
March 17, 2016
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

« First   ‹ Prev
1 2 3