dmd
dmd copied to clipboard
Fix Issue 18119 - Mark if(__ctfe) blocks as SCOPEctfe
Revival of #3572
Thanks for your pull request, @ibuclaw!
Bugzilla references
Auto-close | Bugzilla | Severity | Description |
---|---|---|---|
✓ | 18119 | enhancement | Allow code that may allocated inside __ctfe condition branches in @nogc functions |
Testing this PR locally
If you don't have a local development environment setup, you can use Digger to test this PR:
dub run digger -- build "master + dmd#7509"
this is nasty special casing, then again this is actually useful. please propose a spec change @ibuclaw.
@stefan-koch-sociomantic - I've put in a changelog entry that gives a real world example of who might benefit.
please also put that an expression involving __ctfe even it it is 0 + __ctfe
will not mark the scope.
please propose a spec change
Imho this is not a spec change, but an improvement of the compiler like e.g. optimization.
This might make it easier to get allocators to work at CTFE 😃.
I don't have any answers at this time, but there seems to be a fundamental design problem in the language if we have to resort to something like this. I'd like to see some brainstorming for a more elegant solution.
@JinShil - That's part of why rebasing these old PRs is supposed to achieve. Debate whether they are sound ideas that may need some TLC (or a better implementation), or reject + close related issues.
so .... thinking about this again, in theory we should be able to constant-fold everything around __ctfe
in cases where marking the scope can be done and/or simplifying the expression to only depend on __ctfe
.
@UplinkCoder - what do you mean?
@jacob-carlborg I'll rather support __ctfeAlloc and __ctfeFree.
I'll rather support __ctfeAlloc and __ctfeFree.
@stefan-koch-sociomantic Doesn't matter to me, as long as then end goal works.
Why add a new keyword though?
it would not be a keyword. rather a very magic function :)
and we already have precedent for this. namely builtins.
How would a hypothetical __ctfeAlloc/Free even be related to allowing GC new in __ctfe blocks?
it removes the need for gc in ctfe. currently a @nogc function cannot be ctfe since ctfe has no way of allocating memory without gc. It follows that providing a way to allocate without gc at ctfe will enable ctfe-branches/ctfe-functions to be @nogc
Ctfe should not be a separate language to runtime. I don't think any of these __ctfeXxx function ideas are any good.
I'd like to see this feature added. Can this be revived? There didn't seem to be any opposition. This would be a first step to opening a lot more things to CTFE, e.g. any functions that use RefCounted
.
but there seems to be a fundamental design problem in the language if we have to resort to something like this.
I don't think so. Anything run at compile-time can't use the GC, as it doesn't exist. This is, IMO, more of a correction than a kludge. Really, the only kludgy part is that it needs a specialized form (but then again, the specialized form is nearly always what anyone uses).
@ibuclaw since you don't like ctfe to be another langauge, we could "fake" a malloc call at ctfe.
it would not be a keyword. rather a very magic function :)
You don't need any magic to implement CTFE alloc: https://github.com/dlang/druntime/blob/246d15ac85b2bc7ae7d7a7f61df2ceb80377ed8c/src/core/internal/convert.d#L13-L34
/+
A @nogc function can allocate memory during CTFE.
+/
@nogc nothrow pure @trusted
private ubyte[] ctfe_alloc()(size_t n)
{
if (!__ctfe)
{
assert(0, "CTFE only");
}
else
{
static ubyte[] alloc(size_t x) nothrow pure
{
if (__ctfe) // Needed to prevent _d_newarray from appearing in compiled prorgam.
return new ubyte[x];
else
assert(0);
}
return (cast(ubyte[] function(size_t) @nogc nothrow pure) &alloc)(n);
}
}
@n8sh there's a lot happening in there (it's a template, you have a seemingly unnecessary check for CTFE at the beginning, and then again later). I don't know if I'd consider that not magic.
But it does provide a path forward as a workaround. I'd still rather have the requirements for @nogc
CTFE simply be that you can allocate inside an if(__ctfe)
block.
Wait, I didn't notice the cast. That's interesting.
I tested and it works for my purpose (using GC to allocate in CTFE, C malloc otherwise)
(it's a template, you have a seemingly unnecessary check for CTFE at the beginning, and then again later).
The second __ctfe check is so it can be used with -betterC
.
No, I misunderstood the example. I thought there was some specific magic going on, but really, it is just casting in @nogc
and ensuring the compiler doesn't actually emit any GC calls using if(__ctfe)
. The other parts of the example aren't important (that it's a template, that it asserts __ctfe at the beginning). I tested it separately, and it works exactly as I would want.