new annotation or pragma to mark functions that are intended to be only used during compile time

Hipreme msnmancini at hotmail.com
Sun Feb 23 17:57:58 UTC 2025


On Sunday, 23 February 2025 at 17:07:30 UTC, Ilya wrote:
> On Friday, 21 February 2025 at 14:04:41 UTC, Steven 
> Schveighoffer wrote:
>> Paul Backus pointed out on discord, there is a very large 
>> problem with this mechanism:
>>
>> importing a file with a function that is not a template nor an 
>> auto function means the semantic is skipped for that function. 
>> This means it would be impossible to know that this function 
>> is ctfe-only. The only other solution there is to semantic 
>> every function, which basically negates any wins we get from 
>> not optimizing these functions.
>
> Yes, that's a good point, thanks.
>
>> So reading all the responses here, my impression is:
>>
>> 1. I think it's a necessary idea to have an attribute if we 
>> want this feature. I like using `@__ctfe` as this requires no 
>> new syntax, and actually already compiles (it just doesn't do 
>> the thing expected). What remains to be seen is if we can hook 
>> this properly. `@__ctfe` becomes `@(true)` currently. If not, 
>> then a new attribute is trivial to add to core.attributes.
>
> I've already updated our internal version to use `@__ctfe`, it 
> works just fine.
>
>> 2. If we are going to have a mechanism to flag that code 
>> generation should be avoided, it would be good to also do this 
>> for functions that begin with `assert(__ctfe)`. This at least 
>> helps with existing uses of that mechanism.
>
> As I said in another reply, I think it can't (and shouldn't) be 
> a plugin replacement for `assert(__ctfe)`. But we can do a 
> small migration tool.
>
>> 3. I don't agree with the compiler errors for all uses of 
>> ctfe-only functions at runtime. As you pointed out, this can 
>> be valid for cases. I don't think it's worth the headache, and 
>> I have learned in the past not to pre-optimize for rule 
>> following especially in generic code. Just let the thing 
>> happen as it would.
>
> Oh, so you are saying we will have to add an attribute (because 
> of compiler implementation reasons), but we'll make it work as 
> if it's an `assert(__ctfe)` in the first line anyway?
>
> I don't agree here. Static check allows us to simply drop these 
> functions, without having to rewrite call sites, it plugs 
> naturally into existing `skipCodegen` implementation and it 
> provides faster feedback, helping to set the attributes 
> correctly. It also lets dropping more functions, think 
> templates. If you use `map!ctonly(xs)`, there is no point to 
> codegen `MapResult!(ctonly, xs).front` for example.
>
> The check will reject some code that could be written with 
> asserts, that's correct. But I don't see it as a problem. It's 
> like static vs dynamic types. You can't put a string into an 
> int in a typed language, but in Python you can. Does it make 
> typed languages worse? I'm not sure.
>
> Since we are adding a new annotation, let's make it right. Such 
> that we are absolutely sure we can omit the codegen and no 
> surprises will happen in run time. And if someone wants to have 
> a contrived behavior, like the one in my example, they are 
> welcome to continue using asserts. We are not going to 
> deprecate `assert(__ctfe)`, right?
>
>> 4. To that end, calling a known ctfe-only function should 
>> result in an appropriate `assert(false, "cannot call ctfe-only 
>> function blahblah at runtime")` when doing code generation 
>> instead of the call to a non-existent function that has a 
>> linker error.
>
> I honestly prefer a linker error over a run-time assert :) 
> Sounds like a time bomb.

There are people out there which can't read linker errors, 
contrary to that, I believe that an advanced feature anyway. To 
be fair, nowadays, I understand them enough for that. Maybe we 
could implement that behavior of no-codegen vs a stub with 
assert(false) with the same strategy as `-check=`.

Since assert(`__ctfe`) is existing code, I would say that, 
implementations that skip codegen because of `assert(__ctfe)`, we 
could instead, we could do like `-ctfeskip=stub` and 
`-ctfeskip=yes` or something like that.

While `@__ctfe` would altogether trigger the same behavior as no 
codegen at all, like `-ctfeskip=yes`.

That would bring:
1. More control to one which understand what they're doing by 
using either `@__ctfe` and `-ctfeskip=yes`.
2. Benefits existing code
3. Avoid breaking existing code since the default could be using 
the stub.


More information about the dip.ideas mailing list