static assert(0) in template is a disaster
Dennis
dkorpel at gmail.com
Wed Jun 17 11:39:22 UTC 2020
On Tuesday, 16 June 2020 at 23:01:10 UTC, Paul Backus wrote:
> ...but in fact, the existence of 'before' and 'after' states is
> an unavoidable consequence of how `static if` works. The
> condition of a `static if` statement *must* be evaluated before
> the body is processed by the compiler. Without some mechanism
> for controlling the order in which declarations undergo
> semantic analysis, it would be impossible to implement `static
> if` in the first place.
I don't think it's fundamentally unavoidable. Here's a way to
make it work:
> static if (x) { <body> }
The compiler rewrites it to this:
> static assert(!x);
And it also tries this:
> static assert(x); <body>
If exactly one of the two compiles, you found a solution.
Otherwise it's a contradiction / ambiguity. E.g:
> static if (is(T == int)) {
> alias T = int;
> }
Has 2 solutions: ambiguity.
> static if (!is(T == int)) {
> alias T = int;
> }
Has 0 solutions: contradiction.
>static if (is(T == int)) {
> alias T = int;
> int x;
>}
>static if (!is(typeof(x)) {
> int x;
>}
Has 1 solution:
>static assert(is(T == int));
>alias T = int;
>int x;
>static assert(is(typeof(x));
Now of course, there are several problems:
- this is difficult to implement given the existing dmd codebase
- this is exponentially slow. I'm pretty sure the Boolean
satisfiability problem [0] is reducible to `static if` and
declarations, so compiling D this way is NP-complete.
- do we as programmers want to deal with code that requires
complex constraint solving to understand?
We could make the language more strict by disallowing changing
'already determined' things, like already happens here:
```
struct S {
static if (S.sizeof < 8) {int x;} // technically solvable
}
// Error: variable onlineapp.S.x cannot be further field because
it will change the determined S size
```
I don't yet have an idea how to do this generally, but a first
guess is: at the end of semantic analysis, re-evaluate all static
conditions (static if, static assert, template constraints) and
see if they still hold.
> The ugly truth here is that Walter has designed himself into a
> corner: module-level declarations are not order invariant in D,
> and never will be.
That's not certain. But if we accept and embrace that that D has
a compilation order with mutable state, nothing is stopping us
from allowing this:
```
enum int x = 0;
static foreach (i; 1..5) {
x += i;
}
pragma(msg, x); // 10
```
[0] https://en.wikipedia.org/wiki/Boolean_satisfiability_problem
More information about the Digitalmars-d
mailing list