Issue 20101 - BetterC: Template instantiation in CTFE only context should skip codegen / nogc / ... Phases
Summary: BetterC: Template instantiation in CTFE only context should skip codegen / no...
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P4 enhancement
Assignee: No Owner
URL:
Keywords: betterC, pull
Depends on:
Blocks:
 
Reported: 2019-08-04 07:39 UTC by Johannes Pfau
Modified: 2023-01-08 06:31 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Johannes Pfau 2019-08-04 07:39:48 UTC
In D, we often uses helpers to generate code for string mixins and similar purposes:

--------------------------------------
public string ctfeHelper()(string a)
{
    return "int " ~ a ~ " = 42;";
}

extern(C) int main() @nogc
{
    mixin(ctfeHelper("a"));
    return a;
}
--------------------------------------

With -betterC, this code currently fails with this message:
test.d(3): Error: array concatenation of expression "int " ~ a ~ " = 42;" requires the GC which is not available with -betterC

However, the code is exclusively used in a CTFE-only context where the GC is conceptionally always available.

Note that if ctfeHelper was a regular function, we would have to emit runtime  code, as it is public and could be called from external code. So in that case, the error would be correct and there's no way to make this work (except for making ctfeHelper private, proofing that it's never used at runtime and that it's unreachable from other modules (which is never the case, if you consider explicitly linking to the mangled name to be valid)).

But for this example, where `ctfeHelper` is a template, we could argue that CTFE-only instatiations should be separated from runtime instantiations: If we do not generate code for the template in CTFE contexts, that's still perfectly fine: Anyone calling ctfeHelper at runtime will instantiate the template again, so the codegen can be executed there. And the user should get the errors there, when instantiating the template in a runtime context.

Fixing this would probably involve marking an TemplateInstance as ctfeOnly. However, it seems the implementation would be 99% identical to isSpeculative templates. Consider this code, which already works with -betterC:


--------------------------------------
string ctfeHelper()(string a)
{
    return "int " ~ a ~ " = 42;";
}

extern(C) int main() @nogc
{
    return  __traits(compiles, ctfeHelper("a"));
}

--------------------------------------
Comment 1 Dlang Bot 2023-01-07 00:49:26 UTC
@WalterBright created dlang/dmd pull request #14789 "fix Issue 20101 - BetterC: Template instantiation in CTFE only contex…" fixing this issue:

- fix Issue 20101 - BetterC: Template instantiation in CTFE only context should skip codegen

https://github.com/dlang/dmd/pull/14789
Comment 2 Walter Bright 2023-01-07 00:53:37 UTC
Noting that this worked in the __traits(compiles,...) was the clue I needed. Thanks!
Comment 3 Dlang Bot 2023-01-07 03:03:57 UTC
dlang/dmd pull request #14789 "fix Issue 20101 - BetterC: Template instantiation in CTFE only contex…" was merged into master:

- ab2a21273c951f050be7aef1a1981ff0aefc1bad by Walter Bright:
  fix Issue 20101 - BetterC: Template instantiation in CTFE only context should skip codegen

https://github.com/dlang/dmd/pull/14789