June 05, 2018
On 6/5/18 6:40 AM, Simen Kjærås wrote:
> On Tuesday, 5 June 2018 at 09:36:22 UTC, Gopan wrote:
>> void main()
>> {
>>     immutable n = __ctfe ? 1 : 2;
>>     int[n] a;
>>     assert(a.length == n); // fails, wat
>> }
> 
> That's gotta be a bug - that should give a 'variable n cannot be read at compile time' error. The fact that n is immutable shouldn't be enough to use it at compile time. Filed as https://issues.dlang.org/show_bug.cgi?id=18945.

Indeed it is a bug. Interesting to see what the compiler sees as its AST:

import object;
void main()
{
        immutable immutable(int) n = __ctfe ? 1 : 2;
        int[1] a = 0;
        assert(1LU == cast(ulong)n);
        return 0;
}

This is what -vcg-ast spits out.

Note the int[1].

-Steve
June 05, 2018
On Tuesday, 5 June 2018 at 13:27:35 UTC, Steven Schveighoffer wrote:
> On 6/5/18 6:40 AM, Simen Kjærås wrote:
>> On Tuesday, 5 June 2018 at 09:36:22 UTC, Gopan wrote:
>>> void main()
>>> {
>>>     immutable n = __ctfe ? 1 : 2;
>>>     int[n] a;
>>>     assert(a.length == n); // fails, wat
>>> }
>> 
>> That's gotta be a bug - that should give a 'variable n cannot be read at compile time' error. The fact that n is immutable shouldn't be enough to use it at compile time. Filed as https://issues.dlang.org/show_bug.cgi?id=18945.
>
> Indeed it is a bug. Interesting to see what the compiler sees as its AST:
>
> import object;
> void main()
> {
>         immutable immutable(int) n = __ctfe ? 1 : 2;
>         int[1] a = 0;
>         assert(1LU == cast(ulong)n);
>         return 0;
> }
>
> This is what -vcg-ast spits out.
>
> Note the int[1].
>
> -Steve
This is not bug just not very intuitive.

Since you are declaring a static array the value of n needs to known at compiletime.
so it'll  try to evaluate n at an compile-time context in which n is 1.
however when code-generation for the function is done __ctfe will be false.
Causing the n variable to be initialized to 2.

Therefore n will not be equal to a.length.
June 05, 2018
On 6/5/18 12:10 PM, Stefan Koch wrote:
> This is not bug just not very intuitive.
> 
> Since you are declaring a static array the value of n needs to known at compiletime.
> so it'll  try to evaluate n at an compile-time context in which n is 1.
> however when code-generation for the function is done __ctfe will be false.
> Causing the n variable to be initialized to 2.
> 
> Therefore n will not be equal to a.length.

No, it's definitely a bug. main is not being evaluated at compile time. The real result of this function should be a compile-time error -- __ctfe is a *runtime* value that is always defined based on whether you are __ctfe or not. Therefore, n must be a runtime value, and not usable as a static array dimension.

If the posted code is valid, then this should be valid as well:

static if(__ctfe)
   immutable n = 1;
else
   immutable n = 2;

But it's not.

-Steve
June 05, 2018
On Tuesday, 5 June 2018 at 18:00:05 UTC, Steven Schveighoffer wrote:

> No, it's definitely a bug. main is not being evaluated at compile time. The real result of this function should be a compile-time error -- __ctfe is a *runtime* value that is always defined based on whether you are __ctfe or not. Therefore, n must be a runtime value, and not usable as a static array dimension.
>
> If the posted code is valid, then this should be valid as well:
>
> static if(__ctfe)
>    immutable n = 1;
> else
>    immutable n = 2;
>
> But it's not.
>
> -Steve

I see what you mean.
I fear fixing this bug will not be easy without breaking arguably valid uses.

June 05, 2018
On Tuesday, June 05, 2018 22:08:32 Stefan Koch via Digitalmars-d-learn wrote:
> On Tuesday, 5 June 2018 at 18:00:05 UTC, Steven Schveighoffer
>
> wrote:
> > No, it's definitely a bug. main is not being evaluated at compile time. The real result of this function should be a compile-time error -- __ctfe is a *runtime* value that is always defined based on whether you are __ctfe or not. Therefore, n must be a runtime value, and not usable as a static array dimension.
> >
> > If the posted code is valid, then this should be valid as well:
> >
> > static if(__ctfe)
> >
> >    immutable n = 1;
> >
> > else
> >
> >    immutable n = 2;
> >
> > But it's not.
> >
> > -Steve
>
> I see what you mean.
> I fear fixing this bug will not be easy without breaking arguably
> valid uses.

Any such case should work by either using an enum instead or using an enum to have the value during CTFE and then initialize a const or immutable variable with it. We'd likely need to deprecate the old behavior rather than simply fixing it in order to avoid breaking code, but the result would ultimately be cleaner, and it should be easy for any affected code to be updated. As is standsw the fact that

immutable i = foo();
int[i] arr;

works and uses CTFE whereas

immutable i = foo();

doesn't do any CTFE just increases the confusion of how CTFE works. The fact that __ctfe then affects things further just makes matters worse. CTFE really should only kick in when it has to kick in. That way, it's clean and understandable as to when it kicks in and when it doesn't, and anyone who wants to initialize a local variable with CTFE can always just use an intermediary enum. We have too much confusion over when CTFE kicks in even without this quirk with immutable.

- Jonathan M Davis

June 06, 2018
On Monday, 4 June 2018 at 03:18:05 UTC, Jonathan M Davis wrote:
> [snip]
>
> If you haven't yet, I'd suggest reading

Would make a good blog series?
June 06, 2018
On Wednesday, June 06, 2018 18:18:16 jmh530 via Digitalmars-d-learn wrote:
> On Monday, 4 June 2018 at 03:18:05 UTC, Jonathan M Davis wrote:
> > [snip]
> >
> > If you haven't yet, I'd suggest reading
>
> Would make a good blog series?

What would make a good blog series? Something talking about CTFE?

- Jonathan M Davis

June 07, 2018
On Tuesday, 5 June 2018 at 22:08:32 UTC, Stefan Koch wrote:
> On Tuesday, 5 June 2018 at 18:00:05 UTC, Steven Schveighoffer wrote:
>
>> No, it's definitely a bug. main is not being evaluated at compile time. The real result of this function should be a compile-time error -- __ctfe is a *runtime* value that is always defined based on whether you are __ctfe or not. Therefore, n must be a runtime value, and not usable as a static array dimension.
>>
>> If the posted code is valid, then this should be valid as well:
>>
>> static if(__ctfe)
>>    immutable n = 1;
>> else
>>    immutable n = 2;
>>
>> But it's not.
>>
>> -Steve
>
> I see what you mean.
> I fear fixing this bug will not be easy without breaking arguably valid uses.

Will it be feasible something like

int n = CTFE(foo(3)); //dont limit CTFE to enum or immutable, etc.  You are calling explicitly.
int[n] arr;

So that, we can be explicit about when CTFE kicks in.  In that case, don't assign value to n at runtime as it has been initialized at compile time.  This way, we can get rid of the intermediate enums which are introduced just for the sake of inviting CTFE.  Also, this way, it will not silently break existing code; instead a compilation error must be thrown "value of n not known at compile time" for the below code.

immutable n = foo();
int[n] arr;

Unless called throgh CTFE(....), dont go for CTFE.

Will this work?

Just putting my thoughts... I am no expert.
June 06, 2018
On Thursday, June 07, 2018 04:41:35 Gopan via Digitalmars-d-learn wrote:
> On Tuesday, 5 June 2018 at 22:08:32 UTC, Stefan Koch wrote:
> > On Tuesday, 5 June 2018 at 18:00:05 UTC, Steven Schveighoffer
> >
> > wrote:
> >> No, it's definitely a bug. main is not being evaluated at compile time. The real result of this function should be a compile-time error -- __ctfe is a *runtime* value that is always defined based on whether you are __ctfe or not. Therefore, n must be a runtime value, and not usable as a static array dimension.
> >>
> >> If the posted code is valid, then this should be valid as well:
> >>
> >> static if(__ctfe)
> >>
> >>    immutable n = 1;
> >>
> >> else
> >>
> >>    immutable n = 2;
> >>
> >> But it's not.
> >>
> >> -Steve
> >
> > I see what you mean.
> > I fear fixing this bug will not be easy without breaking
> > arguably valid uses.
>
> Will it be feasible something like
>
> int n = CTFE(foo(3)); //dont limit CTFE to enum or immutable,
> etc.  You are calling explicitly.
> int[n] arr;
>
> So that, we can be explicit about when CTFE kicks in.  In that case, don't assign value to n at runtime as it has been initialized at compile time.  This way, we can get rid of the intermediate enums which are introduced just for the sake of inviting CTFE.  Also, this way, it will not silently break existing code; instead a compilation error must be thrown "value of n not known at compile time" for the below code.
>
> immutable n = foo();
> int[n] arr;
>
> Unless called throgh CTFE(....), dont go for CTFE.
>
> Will this work?
>
> Just putting my thoughts... I am no expert.

The core problem with this is that it's using a runtime variable at compile time, which doesn't normally work. The fact that it works with an immutable variable is a weird quirk based on the fact that it was assumed that the value would be identical at both runtime and compile time, and as already shown in this thread, that results in other bugs.

It would be trivial enough to create a wrapper template so that you can do something like

immutable n = ctfe!(foo());

e.g.

template ctfe(alias value)
{
    enum ctfe = value;
}

The problem is the fact that a runtime variable is being allowed in a context that requires a compile time value. That violates how CTFE normally works, increasing the confusion about when CTFE kicks in, and as shown in this thread, it can result in subtle bugs.

- Jonathan M Davis

June 07, 2018
On Wednesday, 6 June 2018 at 22:19:58 UTC, Jonathan M Davis wrote:
> On Wednesday, June 06, 2018 18:18:16 jmh530 via Digitalmars-d-learn wrote:
>> On Monday, 4 June 2018 at 03:18:05 UTC, Jonathan M Davis wrote:
>> > [snip]
>> >
>> > If you haven't yet, I'd suggest reading
>>
>> Would make a good blog series?
>
> What would make a good blog series? Something talking about CTFE?
>
> - Jonathan M Davis

I meant that stuff describing the nuances and motivations between static/enum/etc. Maybe more tutorial or something on the wiki than blog series? It's the type of thing that isn't obvious to someone new to D, but you explain very well. Better to save it in some place easy to find than let it get buried in Learn.