For this code
--------
import std.meta;
alias tuple = AliasSeq!();
static assert(tuple.length == 2);
alias t0 = tuple[0];
--------
DMD gives the following errors:
bug.d(4): Error: tuple index 0 exceeds 0
bug.d(3): Error: static assert (0LU == 2LU) is false
I expect static assert to be checked first.
Comment #1 by pro.mathias.lang — 2020-01-04T19:17:32Z
Just hit this bug, but straight in Druntime.
Test case:
```
version (NonExistent)
{
alias FILE = void*;
}
else
static assert("Unsupported platform");
FILE getSomething();
```
This will output "test.d(8): Error: undefined identifier FILE" with a recent compiler.
This is a common pattern for platform support. I'm not sure we could guarantee the order of evaluation here, but if we don't, we need to go through our libs and provide dummy declarations.
Comment #2 by b2.temp — 2020-01-04T20:02:16Z
Yes but you indirectly assert the .length property of the message. If you
static assert(0, "Unsupported platform");
Then the static assert is displayed at least. Maybe it was just a typo ?
Comment #3 by pro.mathias.lang — 2020-01-05T00:43:45Z
Right, it was a typo.
The case I encountered though, was triggered inside of druntime because the C runtime I was targeting did not have a definition for 'FILE'.
As a result, the compiler hit a limit in the number of error (apparently 20).
Correct test case:
```
version (NonExistent)
{
alias FILE = void*;
}
else
static assert(0, "Unsupported platform");
FILE getSomething1();
FILE getSomething2();
FILE getSomething3();
FILE getSomething4();
FILE getSomething5();
FILE getSomething6();
FILE getSomething7();
FILE getSomething8();
FILE getSomething9();
FILE getSomething10();
FILE getSomething11();
FILE getSomething12();
FILE getSomething13();
FILE getSomething14();
FILE getSomething15();
FILE getSomething16();
FILE getSomething17();
FILE getSomething18();
FILE getSomething19();
FILE getSomething20();
```
This does not display the assert. Commenting one of the function does.
Comment #4 by turkeyman — 2024-11-12T13:53:17Z
druntime and phobos are riddled with this issue!
static assert needs to tell you the error it's checking for _before_ the errors relating to the symptoms of the error it's checking for, otherwise it's useless.
In druntime, all the cases like:
```
version (Posix)
public import core.sys.posix.stdc.time;
else version (Windows)
public import core.sys.windows.stdc.time;
else
static assert(0, "unsupported system");
@system time_t mktime(scope tm* timeptr);
```
1> time.d(37): error : undefined identifier `tm`
The static assert doesn't emit any error message at all!
It's difficult to imagine how the compiler could be certain that `tm` is not a thing before it's able to resolve `assert(0)`. The version sequence can be resolved immediately, and static assert(0) can be resolved immediately too...
This is actually a pretty serious bug; we can't write portable code if we can't expect top-level static assert's to inform us that symbols are missing or that a platform is not supported!
Comment #5 by turkeyman — 2024-11-12T13:58:19Z
I got rid of everything, this is all that's left:
```
static assert(0, "unsupported system");
@system time_t mktime(scope tm* timeptr);
```
No version's, no imports, nothing... even in this code, here's the compiler's output:
time.d(20): error : undefined identifier `tm`
Why did it complain about `tm` but not `time_t`?
Why did it completely ignore the static assert?
I'm raising the importance on this bug... it's actually severe.
Comment #6 by dkorpel — 2024-11-12T14:12:37Z
(In reply to Manu from comment #5)
> No version's, no imports, nothing... even in this code, here's the
> compiler's output:
>
> time.d(20): error : undefined identifier `tm`
What compiler version are you using? I'm getting:
2.109
```
time.d(3): Error: undefined identifier `time_t`
time.d(3): Error: undefined identifier `tm`
time.d(1): Error: static assert: "unsupported system"
```
2.110 (nightly):
```
time.d(1): Error: static assert: "unsupported system"
```
Comment #7 by turkeyman — 2024-11-12T14:14:52Z
LDC 1.39.0 (DMD v2.109.1, LLVM 18.1.6)
Comment #8 by dkorpel — 2024-11-12T14:27:15Z
This will be fixed once dmd 2.110 and LDC 1.40 are released. The static assert(0, "unsupported system") static asserts are short-circuited as of the fix for issue 24645. That also fixes Mathias' test case. The remaining issue is from OP:
```
alias AliasSeq(T...) = T;
alias tuple = AliasSeq!();
static assert(tuple.length == 2);
alias t0 = tuple[0];
```
The problem here is that `alias t0 = tuple[0]` is semantic1, while static assert is semantic2, as can be seen with the `-v` switch:
```
semantic app
app.d(4): Error: sequence index `0` out of bounds `[0 .. 0]`
semantic2 app
app.d(3): Error: static assert: `0LU == 2LU` is false
```
This could be fixed by evaluating static asserts in semantic1, but there probably was a reason to do it in semantic2, so I'm not sure.
Comment #9 by robert.schadek — 2024-12-13T18:50:33Z