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