On 04/17/2017 09:29 PM, Jesse Phillips wrote:
On Thursday, 13 April 2017 at 21:33:28 UTC, ag0aep6g wrote:
[...]
By the way, in my opinion, `case li[0]:` shouldn't compile with the
static immutable `list`. `list` and `li[0]` are dynamic values. The
compiler only attempts (and succeeds) to evaluate them at compile time
because they're typed as immutable. The way I see it, that only makes
things more confusing.

This is very interesting. I wonder if the compiler is still unrolling
the loop at compile time since it functions as expected; It certainly
needs that deprecation though.

It's really weird. I thought the loop would just not be unrolled at all. However, both `case`s seem to be generated as expected. So it behaves like a static foreach in that regard. But when you use `li` as a dynamic value (e.g. `writeln(li[1])`), it's suddenly empty. Seems that dmd can't decide what to do, so it does a little bit of both.

Maybe I was wrong, and the loop in your code is a static foreach, but at some point there's a bug that makes dmd think it's dealing with run-time values.

The behavior is also completely inconsistent.

With ints, the program compiles and the assert passes:

----
alias AliasSeq(stuff ...) = stuff;
immutable list = AliasSeq!(1, 2);

void main()
{
    switch(1)
    {
        foreach(li; list)
        {
            case li: enum e = li; assert(e == li); return;
        }
        default:
    }
}
----

With strings, the program doesn't compile:

----
alias AliasSeq(stuff ...) = stuff;
immutable list = AliasSeq!("foo", "bar");

void main()
{
    switch("foo")
    {
        foreach(li; list)
        {
            case li: enum e = li; assert(e == li); return;
/* "Error: case must be a string or an integral constant, not li" */
        }
        default:
    }
}
----

And with structs (your case), it compiles with a deprecation warning and behaves schizophrenically:

----
alias AliasSeq(stuff ...) = stuff;
struct S { int x; }
immutable list = AliasSeq!(S(1), S(2));

void main()
{
    switch(1)
/* Deprecation: 'switch' skips declaration of variable */
    {
        foreach(li; list)
        {
            case li.x: enum e = li; assert(e == li); return;
/* The assert fails. */
        }
        default:
    }
}
----

In my opinion, they should all simply be rejected. But I have no idea what's intended by the compiler writers. It's a mess.

With enum/alias, they all compile and work as expected, of course.

Reply via email to