static assert(0) in template is a disaster
Paul Backus
snarwin at gmail.com
Tue Jun 16 23:01:10 UTC 2020
On Tuesday, 16 June 2020 at 22:16:34 UTC, Dennis wrote:
> On Tuesday, 16 June 2020 at 18:14:26 UTC, Nils Lankila wrote:
>>> template example(T)
>>> {
>>> static assert(__traits(hasMember, T, "x"));
>>> alias example = T.x;
>>> }
>>>
>>> struct S
>>> {
>>> static if (!__traits(compiles, example!S)) {
>>> int x;
>>> }
>>> }
>>>
>>> static assert(is(typeof(example!S) == int));
>>
>> that's unfortunate, looks like the problem cant be solved then.
>
> In my opinion, the fact that that compiles is a blatant bug.
> However, the D specification is not thorough enough to
> conclusively say. Even if we define it better and patch the
> compiler, unfortunately the paradoxical "if this doesn't
> compile yet, make it compile" pattern has been adopted in the
> wild so it would be a breaking change. To see why it's
> problematic, ask yourself why this compiles:
>
> ```
> static assert(x == 3);
> static if (!is(typeof(x))) immutable x = 3;
> static if (!is(typeof(x))) immutable x = 5;
> ```
>
> I've written about this in more detail before:
> https://forum.dlang.org/post/tlpogchogwsopswgbpdu@forum.dlang.org
I agree that this is a bug, but it is a bug in the design of the
language itself, not the implementation.
You write in your linked post that
> The 'before' and 'after' are implementation details showing up
> as a result of underspecification.
>
> Module level declarations are supposed to be order invariant.
...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.
In more principled languages (e.g., Lisps), this ordering is
explicit, and chosen by the programmer: a macro takes the
'before' state as its input and produces the 'after' state as its
output, and the programmer is free to compose as many of them as
they like in any order. In D, the ordering is implicit, and
chosen by the compiler via on-demand semantic analysis, but apart
from that it is fundamentally the same.
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.
More information about the Digitalmars-d
mailing list