No need for version expression is a lie

Adam D Ruppe destructionator at gmail.com
Thu Aug 24 18:04:36 UTC 2023


On Thursday, 24 August 2023 at 17:03:20 UTC, Walter Bright wrote:
> Not impossible, just initially a mite tedious. One can still 
> incrementally port to AdrOS by adding:
>
> ```
> version (Windows)
> {
>      enum x = 7;
> }
> else version (AdrOS)
> {
>      enum x = 0; // FIXME
> }
> else
>      static assert(0);
> ```

So your solution to how static assert(0) sucks is to literally 
add a branch that doesn't use it.

If this isn't a full concession, I don't know what is!


But, I'd point out that this kind of thing is even worse than not 
having the `else static assert(0)` branch at all. Suppose you 
wrote it like this in the first place:

```
version(Windows)
   enum x = 8;
version(linux)
   enum x = 8;

// somewhere else

version(Windows)
   enum y = 9;
version(linux)
   enum y = 7;
```

You port it to AdrOS.

```
import that;
void main() {
    auto thing = x;
}
```

You now get a nice error: undefined identifier "x". *as you use 
it*, the compiler tells you it is missing and you know to go fix 
it. Then later, when you use y, you again get undefined 
identifier and you go back and add it. It is incrementally ported 
- always compiling the core, with more advanced test cases 
failing until you fill in those features.

Now, contrast to the static assert pattern:

```
version(Windows)
   enum x = 8;
else version(linux)
   enum x = 8;
else static assert(0);

// somewhere else

version(Windows)
   enum y = 6;
else version(linux)
   enum y = 7;
else static assert(0);
```

You port it to AdrOS.

```
import that;
void main() {
    auto thing = x;
}
```

You get compile errors before you even get into main! You have to 
do *all* the work up front to test *any* of it. So, we do the 
tedious thing you suggested:

```
version(Windows)
   enum x = 8;
else version(linux)
   enum x = 8;
else version(AdrOS)
   enum x = 9;
else static assert(0);

// somewhere else

version(Windows)
   enum y = 6;
else version(linux)
   enum y = 7;
else version(AdrOS)
   enum y = 0; // FIXME
else static assert(0);
```

After who knows how many hours, you've finished all that tedious 
nonsense and can finally compile your test program again:


```
import that;
void main() {
    auto thing = x;
}
```

Yay, hello world finally works!

Then a month later, you try to use `y`, forgetting that there's a 
FIXME. The program fails in mysterious ways, throwing some 
invalid flag exception or something, but the docs say y is a 
valid flag.

A few hours later, you try to `printf("%d", y)` and you see a 0. 
Oh yeah, you never ported that. Time to grep for FIXME again.

Complete waste of time with zero help from the compiler.

It is better to never use static assert(0) at all like this. It 
is good inside a template to validate arguments that the user 
might fix and try recompiling again.

It is not good at module level where it just wastes time.


> I guarantee it because it always happened when defaults were 
> used for unknown systems.

I'm not suggesting using defaults for unknown systems.

> I prefer a bit of tedium to debugging hell.

I prefer neither.


More information about the Digitalmars-d mailing list