Thread overview
[Issue 15166] [REG2.069-devel] spurious statement not reachable warning in static foreach loop
[Issue 15166] [Ref 2.069-devel] spurious statement not reachable warning in static foreach loop
Oct 07, 2015
Kenji Hara
Oct 07, 2015
Kenji Hara
Oct 10, 2015
Martin Nowak
Oct 12, 2015
Martin Nowak
Oct 12, 2015
Martin Nowak
Oct 12, 2015
Martin Nowak
October 07, 2015
https://issues.dlang.org/show_bug.cgi?id=15166

--- Comment #1 from Kenji Hara <k.hara.pg@gmail.com> ---
Introduced in: https://github.com/D-Programming-Language/dmd/pull/4790

I'm not sure how we can "fix" this and issue 14835.

--
October 07, 2015
https://issues.dlang.org/show_bug.cgi?id=15166

Kenji Hara <k.hara.pg@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|[Ref 2.069-devel] spurious  |[REG2.069-devel] spurious
                   |statement not reachable     |statement not reachable
                   |warning in static foreach   |warning in static foreach
                   |loop                        |loop

--
October 10, 2015
https://issues.dlang.org/show_bug.cgi?id=15166

--- Comment #2 from Martin Nowak <code@dawg.eu> ---
This is as annoying as go's stupid "unused variable" warning, at least during development.

> I'm not sure how we can "fix" this and issue 14835.

I guess the fix would be to mark those returns as dependent on the template
types and not account for them when computing not reachable statements, but
that sounds like quite a difficult change.
I guess we might fix this in vibe.d but it might break a lot more code.

--
October 12, 2015
https://issues.dlang.org/show_bug.cgi?id=15166

--- Comment #3 from Martin Nowak <code@dawg.eu> ---
I think something along this line could work.

override void visit(ConditionalStatement s)
{
    if (s.condition.include(null, null))
    {
        result = s.ifbody.blockExit(func, mustNotThrow);
        // mark as conditional fallthru, see Bugzilla 14835
        if (!s.elsebody) result |= BEconditional;
    }
    else if (s.elsebody)
        result = s.elsebody.blockExit(func, mustNotThrow);
    else
        result = BEfallthru;
}

if (!(result & (BEfallthru | BEconditional)) && !s.comeFrom())
{
    if (s.blockExit(func, mustNotThrow) != BEhalt && s.hasCode())
        s.warning("statement is not reachable");
}

But for this to work ConditionalStatement must no longer be flattened before computing blockExit, thus making this change very big (and somewhat risky).

--
October 12, 2015
https://issues.dlang.org/show_bug.cgi?id=15166

--- Comment #4 from Martin Nowak <code@dawg.eu> ---
A workaround is to use a variable.

bool res = true;
foreach (index, element; Group1.expand)
{
    static if (!is(Group1.expand[index] == Group2.expand[index]))
    {
        res = false;
        break;
    }
}
return res;

--
October 12, 2015
https://issues.dlang.org/show_bug.cgi?id=15166

Martin Nowak <code@dawg.eu> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|---                         |DUPLICATE

--- Comment #5 from Martin Nowak <code@dawg.eu> ---


*** This issue has been marked as a duplicate of issue 14835 ***

--
October 13, 2015
https://issues.dlang.org/show_bug.cgi?id=15166

Steven Schveighoffer <schveiguy@yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |schveiguy@yahoo.com

--- Comment #6 from Steven Schveighoffer <schveiguy@yahoo.com> ---
(In reply to Martin Nowak from comment #4)
> A workaround is to use a variable.

I think this may be the right answer.

It boils down to this:

static if(someCondition) return false;
return true;

Which you would normally write with else, but it's not so simple in this case, because the "else" would be part of the loop.

I'm curious why the return short-circuits the loop. In other words, why aren't all the "return false" statements besides the first one flagged for unreachability? Is it because the compiler stops generating the statements? I mean, if you rewrote as a bunch of static ifs, then wouldn't you have the same problem?

Another possible answer is to do this:

private bool compare(alias Group1, alias Group2)()
{
    foreach (index, element; Group!(Group1.expand, void).expand)
    {
        static if(index == Group1.expand.length)
            return true;
        else static if (!is(Group1.expand[index] == Group2.expand[index]))
            return false;
    }
}

--