April 07, 2020
On Tuesday, 7 April 2020 at 17:52:44 UTC, Jacob Carlborg wrote:
>
> void foo()
> {
>     assert(__ctfe);
> }
>
> void main() @system
> {
>     try
>         foo();
>     catch (AssertError)
>     {}
> }

firstly Does anybody actually do this?
secondly your program either complies with no change (i.e. the assert never fired), or you get a message telling you that ctfe-only functions can't be called at runtime.
April 07, 2020
On 4/7/2020 12:33 AM, Stefan Koch wrote:
> On Tuesday, 7 April 2020 at 06:55:59 UTC, Walter Bright wrote:
>> Sounds ok to me, as long as the assert(__ctfe) is the first statement in the function body.
>>
>> Though I would check the linker map file to see if the linker didn't already omit functions that were never called.
> 
> In order to support contracts we need to go through all the statements in the merged contract .... but I can split that out.

You could move it up earlier in the semantic analysis. When semantic analysis starts, simply check the first statement, and set a flag "no code gen" in the FuncDeclaration.
April 07, 2020
On 4/7/2020 2:17 AM, Atila Neves wrote:
> I think the problem with relying on the linker is that the user still pays with longer compile times for codegen that isn't needed.

True
April 07, 2020
On 4/7/20 5:17 AM, Atila Neves wrote:
> On Tuesday, 7 April 2020 at 06:55:59 UTC, Walter Bright wrote:
>> Sounds ok to me, as long as the assert(__ctfe) is the first statement in the function body.
>>
>> Though I would check the linker map file to see if the linker didn't already omit functions that were never called.
> 
> I think the problem with relying on the linker is that the user still pays with longer compile times for codegen that isn't needed.

Isn't there an issue for better C as well? If a function can't be compiled in betterC but is valid for CTFE, then this could be a potential solution.

I don't know how this works today.

-Steve
April 07, 2020
On 4/7/20 12:53 PM, Johannes Pfau wrote:
> The example above actually already compiles with -betterC, as the check
> is done in codegen phase! But some betterC checks seem to be done in
> semantic. This doesn't work yet:
> 
> ------------------------
> string generateMixin(T)(string b)
> {
>      assert(__ctfe);
>      return typeid(T).stringof ~ " " ~ b ~ ";";
> }
> 
> void main() @nogc
> {
>      mixin(generateMixin!string("b"));
> }
> ------------------------
> dmd -betterC test.d -c
> test.d(4): Error: TypeInfo cannot be used with -betterC

Ironically, ctfe can't deal with TypeInfo today.

In the past, the issue was for functions that use TypeInfo is that the non-CTFE branch uses TypeInfo, and that can't be used in betterC, but the CTFE branch doesn't use TypeInfo, but the compiler wants to build the whole function.

So while this is still a problem, I don't think this fix will change that.

-Steve
April 08, 2020
Am Tue, 07 Apr 2020 17:13:54 -0400 schrieb Steven Schveighoffer:

> On 4/7/20 12:53 PM, Johannes Pfau wrote:
>> The example above actually already compiles with -betterC, as the check is done in codegen phase! But some betterC checks seem to be done in semantic. This doesn't work yet:
>> 
>> ------------------------
>> string generateMixin(T)(string b)
>> {
>>      assert(__ctfe);
>>      return typeid(T).stringof ~ " " ~ b ~ ";";
>> }
>> 
>> void main() @nogc {
>>      mixin(generateMixin!string("b"));
>> }
>> ------------------------
>> dmd -betterC test.d -c test.d(4): Error: TypeInfo cannot be used with
>> -betterC
> 
> Ironically, ctfe can't deal with TypeInfo today.
> 
> In the past, the issue was for functions that use TypeInfo is that the non-CTFE branch uses TypeInfo, and that can't be used in betterC, but the CTFE branch doesn't use TypeInfo, but the compiler wants to build the whole function.
> 
> So while this is still a problem, I don't think this fix will change that.
> 
> -Steve

I'm not sure what exactly you're referring to, but this code compiles perfactly fine:
--------------------------
 string generateMixin(T)(string b)
 {
      assert(__ctfe);
      return "auto a = " ~typeid(T).stringof ~ ";";
 }

 void main() @nogc
 {
      mixin(generateMixin!string("b"));
      pragma(msg, generateMixin!string("b"));
 }
--------------------------


But it does not copile with -betterC. The point here is that the "Error: TypeInfo cannot be used with -betterC" message does not apply to CTFE- only functions, so this PR should be able to disable the check.

My primary fear here is that the current implementation checks the function too late in semantic and therefore such checks (or the "ensure no non-ctfe function calls ctfe-only functions" check are much more difficult to implement than they should be. Using a pragma or attribute would easily solve this.

Maybe you'd have to introduce something analog to "safetyInProgress" which is "ctfeOnlyInProgress" to make this assert(__ctfe) detection fully usable? But I think this adds way to much complexity. Even right now, the code of the PR could probably be reduced by 1/2 when just using a pragma.

-- 
Johannes
April 08, 2020
On Wednesday, 8 April 2020 at 07:09:11 UTC, Johannes Pfau wrote:
> Am Tue, 07 Apr 2020 17:13:54 -0400 schrieb Steven Schveighoffer:
>
>> On 4/7/20 12:53 PM, Johannes Pfau wrote:
>>> [...]
>> 
>> Ironically, ctfe can't deal with TypeInfo today.
>> 
>> In the past, the issue was for functions that use TypeInfo is that the non-CTFE branch uses TypeInfo, and that can't be used in betterC, but the CTFE branch doesn't use TypeInfo, but the compiler wants to build the whole function.
>> 
>> So while this is still a problem, I don't think this fix will change that.
>> 
>> -Steve
>
> I'm not sure what exactly you're referring to, but this code compiles perfactly fine:
> --------------------------
>  string generateMixin(T)(string b)
>  {
>       assert(__ctfe);
>       return "auto a = " ~typeid(T).stringof ~ ";";
>  }
>
>  void main() @nogc
>  {
>       mixin(generateMixin!string("b"));
>       pragma(msg, generateMixin!string("b"));
>  }
> --------------------------
>
>
> But it does not copile with -betterC. The point here is that the "Error: TypeInfo cannot be used with -betterC" message does not apply to CTFE- only functions, so this PR should be able to disable the check.
>
> My primary fear here is that the current implementation checks the function too late in semantic and therefore such checks (or the "ensure no non-ctfe function calls ctfe-only functions" check are much more difficult to implement than they should be. Using a pragma or attribute would easily solve this.
>
> Maybe you'd have to introduce something analog to "safetyInProgress" which is "ctfeOnlyInProgress" to make this assert(__ctfe) detection fully usable? But I think this adds way to much complexity. Even right now, the code of the PR could probably be reduced by 1/2 when just using a pragma.

The detection of assert __ctfe in the function body _can_ be done very early in the process
I do not want to introduce a pragma or magic annotatation.
When existing the language is perfectly able to express (only runs at ctfe).

Also the PR I have open is _only_ for that.
I or someone else, might write code which does the detection earlier and then disables betterC checks, but this is only about turning off codegen.

April 08, 2020
On Wednesday, 8 April 2020 at 08:42:52 UTC, Stefan Koch wrote:
> When existing the language is perfectly able to express (only runs at ctfe).

assert(__ctfe) does not express that you STATICALLY know it only runs at ctfe, it is a RUNTIME error and it is impossible to statically decide whether the function may actually get called outside ctfe context.
April 08, 2020
On Wednesday, 8 April 2020 at 09:11:45 UTC, Dennis wrote:
> On Wednesday, 8 April 2020 at 08:42:52 UTC, Stefan Koch wrote:
>> When existing the language is perfectly able to express (only runs at ctfe).
>
> assert(__ctfe) does not express that you STATICALLY know it only runs at ctfe, it is a RUNTIME error and it is impossible to statically decide whether the function may actually get called outside ctfe context.

The only reason why I used assert (__ctfe) not static assert (__ctfe) is because that's impossible to express.
since __ctfe is a magic runtime variable that's hardwired to be zero in the non-ctfe case.
April 08, 2020
On Tuesday, 7 April 2020 at 21:11:11 UTC, Steven Schveighoffer wrote:
> On 4/7/20 5:17 AM, Atila Neves wrote:
>> On Tuesday, 7 April 2020 at 06:55:59 UTC, Walter Bright wrote:
>>> Sounds ok to me, as long as the assert(__ctfe) is the first statement in the function body.
>>>
>>> Though I would check the linker map file to see if the linker didn't already omit functions that were never called.
>> 
>> I think the problem with relying on the linker is that the user still pays with longer compile times for codegen that isn't needed.
>
> Isn't there an issue for better C as well? If a function can't be compiled in betterC but is valid for CTFE, then this could be a potential solution.
>
> I don't know how this works today.
>
> -Steve

Good question, me neither.