Quantum Superposition Observed in DMD at Compile Time

Meta jared771 at gmail.com
Mon Jul 1 01:42:36 UTC 2019


Jokes aside, this is very strange behaviour.

struct Test(T...)
{
     this(T ts)
     {
         foreach (i, t; ts)
         {
             int[ts.length] nums;
             if (i % 2 == 0)
             {
                 nums[i / 2] = i;
             }
             else
             {
                 nums[(i - 1) / 2] = i; // Error:array index 
9223372036854775807 is out of bounds nums[0 .. 4]
             }
         }
     }
}

void main()
{
     auto t = Test!(int, string, double, bool)(0, "", 0, false);
}

Of course, the only possible way (i - 1) / 2 can be 
9223372036854775807 is if i == 0 and thus i - 1 underflows. 
However, this should never be possible because the else branch 
should only be taken when i > 0.

After some testing, I realized that this is a very weird 
side-effect of constant folding. Regardless of whether the "else" 
branch will be taken at runtime, nums[(i - 1) / 2] is computed 
*at compile time* for each loop... but, it's not actually a loop. 
This is a static foreach (old-style, but this problem occurs with 
`static foreach` as well). The loop body is unrolled N times 
(where N == ts.length), and as expected, when I change the 
foreach to a regular for-loop, this problem goes away. Also 
changing the runtime if to static if fixes it.

This is very strange behaviour, but understandable after some 
investigation. What I don't quite know is whether there should be 
a bug report opened for this. It's not technically a bug, I don't 
think, but it is certainly unexpected and arguably should be 
fixed.


More information about the Digitalmars-d mailing list