I was distracted and with a unfocused mind, sorry for the late reply.
Walter:
> We thought about this approach and deliberately did not do it.
Thank you for your answer. Sometimes it doesn't harm to think again a bit about
a topic.
> It is not predictable at compile time whether a function can be executed
> at compile time or not (the halting problem). Therefore, you'll wind up
> with cases that silently fail at compile time, and so are put off until
> runtime. The user cannot tell (without looking at assembly dumps) if it
> happened at compile time or not.
>
> Instead, we opted for a design that either must run at compile time, or
> must run at run time. Not one that decides one way or the other in an
> arbitrary, silent, and ever-changing manner.
In this discussion I was talking about running just the pre-conditions, and not
the whole function, and not its post-condition.
This is different because:
- Pre-conditions are usually small or smaller than function bodies;
- Pre-conditions are usually meant to be fast (and not slower than the function
body), so they are probably not too much heavy to run. pre-conditions, unlike
debug{} code are meant to run often;
- Pre-conditions are often pure (mine). If the "feature" I am talking about
gets introduced, D programmers will be encouraged to write more pure
preconditions (this probably explains why most other Contract-based systems
I've seen don't use free code in contracts as D does, but use a specific
expression language. This forces them to be pure and simpler, more fit for
analysis!). Even if a function is not marked as "pure", what matters in this
discussion is to its pre-condition to be CTFE-pure.
The problem you list is of course important for the normally run CT functions,
and I agree with the decision. But it's much less important for my idea,
because I've seen that finding bug in code is essentially never a deterministic
process, it's very probabilistic. People find only some bugs (people today find
new bugs even in 10+ years old very-high-quality C code used by everyone
(Zlib)), lint tools (including the static analysis flag of Clang I've shown
recently) find only some other bugs, and different lints find different bugs.
One important factor for those tools is to reduce false positives as much as
possible (even if this increases false negatives a little), and this idea of
mine produced zero false alarms (if the pre-conditions are written correctly).
This feature is useful because when in your code you have struct literals like:
Foo f1 = Foo(10, -20);
The compiler is able at compile-time to tell you that line of code is wrong
because -20 is not acceptable :-) This is useful in many situations. This
feature works only if the arguments are known at compile-time, this is a strong
limitation, but I think it's better to have it anyway.
Even if this feature sometimes gets disabled by turning a CTFE-pure function
pre-condition into not CTFE-pure code as you say, the programmer doesn't need
to care a lot about this, because even if this change doesn't allow to catch a
bug in the code, other bugs too are not found by the compiler. All static
analysis tools do the same, they sometimes find a bug, but if you change the
code in a way they don't fully understand, they don't find the bug any more.
This is why I think your argument doesn't hold.
The feature I have proposed is not a language feature, it's a compiler feature
(the only change is in user code, that's encouraged to create CTFE-pure
pre-conditions). This means that even if DMD doesn't want this idea, future D
compilers will be free to adopt it. And from the direction of the tide (as
Clang adds better and better analysis for C and C++ code) I think this will be
seen as a cheap but useful compiler feature to add (a "low-hanging fruit"
because the only needed compiler change I see needed is to not stop the
compilation if a pre-condition of a function with statically known arguments
turns out to be not runnable).
Bye,
bearophile