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

Ilya ilya.yanok at gmail.com
Sun Feb 23 17:07:30 UTC 2025


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.



More information about the dip.ideas mailing list