I think there are a lot of potential downsides to having to mark functions as compiler evaluable, e.g.:
Many functions will end up been marked as such. What's the point in a language that infers type to reduce clutter if it is cluttered with annotations everywhere?
The annotation will spread through everyones code base, because if I want a function to be compiler evaluable then every function it calls needs to be compiler evaluable. This is what happened in C++ with
const, seemed like a great idea to explicitly mark intent! In practice it was a nightmare were people had to go through whole existing codebases and annotate with const. Same thing with compiler evaluable, there will be whole discussions on Swift Evolution about which functions in the standard library need to gain the annotation.
To address points raised directly:
I don't think it achieves that goal. If I write:
val example = f()
How do I know that f will be called at compile time? An annotation that would achieve that is:
@compilerEvaluated val example = f()
The compiler could flag this with a warning/error to say that it couldn't evaluate
If you wanted to ensure that the function you wrote was compiler evaluable then write a test using
@compilerEvaluated, as above. This does not make compiler evaluated part of a methods ABI, which I think is a good thing.
Compiler evaluable should be an optimization, not part of the definition.
PS For consistency I also object to
#if, etc for the same reasons, these shouldn't be placed as burdens on the programmer. It's not 1970, we are not writing C. Compilers have moved on and many languages now shy away from overly annotated code.