Quantum Superposition Observed in DMD at Compile Time

Exil Exil at gmall.com
Mon Jul 1 02:29:57 UTC 2019


On Monday, 1 July 2019 at 01:42:36 UTC, Meta wrote:
> 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.

If anything the foreach should be a regular loop. The only time 
CTFE should happen is with static foreach(). But that didn't 
exist until recently. Have no doubt this will break code, though 
they would just need to stick static infront of the loop to fix 
it? Possibly a deprecation? Doesn't make sense to have foreach() 
behave like static foreach() now that it exists.


More information about the Digitalmars-d mailing list