-
-
Notifications
You must be signed in to change notification settings - Fork 98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Evaluate Pure Functions With CTFE #177
base: master
Are you sure you want to change the base?
Conversation
This should not need a DIP. It is effectively an optimization ran by the frontend to minimize code that is ran at runtime. From the spec:
|
One advantage of Don Clugston' idea is that it allows to disable code generation for functions that are only used at compile-time. // before:
string calc(int a, int b) { /* ... */ }
// ...
enum c = calc(1, 2);
// Result: `calc` is emitted in the binary - bad.
// Attempt 1:
enum c = (int a, int b) { /* body of calc */ }(1, 2);
// Result:
// a) `calc` is not part of the binary - good
// b) `calc` is no longer reusable code - bad
// Attempt 2:
enum calc(int a, int b) = { /* body of calc */ }();
enum c = calc!(1, 2);
// Result:
// a) `calc` is not part of the binary - good
// b) `calc` is still reusable code - good
// c) `calc` is now a template which:
// c.1) allows memoization - good
// c.2) for many distinct template arguments is slower than plain ctfe - bad. I think the best solution would be to use regular functions, but for the language to recognize a pattern like |
Another option is for the language to guarantee that functions marked with |
I think adding |
A pragma sounds nice, too. It would solve the composition problem that this DIP has: Consider two pure functions |
Got to add that determining CTFEability based on the function and call seems at least on the surface a more principled approach than a pragma. Also, it will CTFE existing code. |
There is no composition problem.
Doing constant folding depth first, which is how it is done now and how it's done everywhere else is:
|
The linker is supposed to remove functions that are never called. |
@WalterBright cool, all I'm saying is that the depth-first folding would be good to mention in the DIP in addition to here. Just paste your text there! :) |
The issue is that the linker thinks those functions are used and as a result, betterC programs fail to link when they use phobos templates such as Edit: |
It recently occurred to me that this is sort of a breaking change with respect to unit tests and test coverage. Many unit tests use literals, and if they are testing pure functions then those tests will be constant folded once this DIP is active. Since code run during ctfe is not traced, the coverage amount will suddenly drop massively for certain projects. Furthermore, some code paths will actually not be tested anymore. int fooSoft() {return 0;}
int fooAsm() {asm{naked; mov RAX, 0; ret;}}
int foo() {return __ctfe ? fooSoft() : fooAsm();}
unittest {
assert(foo() == 0); // expected to cover fooAsm
static assert(foo() == 0);
} Suddenly bugs in I think the DIP should address this. |
About the Prior Work section: Isn't C++'s consteval exactly what Don Clungston suggested |
@PetarKirov wrote:
I'd say, recognize The biggest difference of recognizing |
I'm concerned that automatically evaluating pure calls with literals at compile-time may slow down compilation. How about only doing this when |
Inspired by Don Clugston's idea to add
__ctfe
as a function attribute.