You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Release-only wrong result in integer for loop: local bound inside loop range expression clobbers a local slot #20732
Release-only wrong result in integer for loop: local bound inside loop range expression clobbers a local slot
Repro steps
//// repro.fsx ////// dotnet fsi --optimize- repro.fsx prints: 100// dotnet fsi --optimize+ repro.fsx prints: 50letf k =
k +(for_in max 0(k -50)..0do stdout.Write ""0)
printfn "%d"(f 100)
Expected behavior
The behavior without optimization is correct. f k is equivalent to k+0, so f 100 should be 100.
Actual behavior
With optimization on, the generated IL spills k off the stack into a local variable slot, but then when evaluating the loop start expression, max needs a local to store k - 50.
GenIntegerForLoop puts that local in the same slot. That clobbers k.
In my first example the start expression is the culprit. But the end expression has the same problem when the optimizer rewrites a loop like for i in 0 .. arr.Length - 1 C#-style. The local can take the loop variable's own slot, and the loop never terminates. Example:
//// repro2.fsx ////// dotnet fsi --optimize- repro2.fsx prints: 0 1 2// dotnet fsi --optimize+ repro2.fsx prints: 0 0 0 0 0 ... foreverletf(xs:int[])n =// this could be any side-effect-free expr that binds a localfor i in0..(if max 0(n -1)>0then xs else xs).Length -1do
printf "%d" i
f [|1;2;3|]1
Known workarounds
Bind the loop's start and/or end to locals with let. Use for x in startVar .. endVar do instead of putting complex expressions directly inside the in _ .. _ part of the loop.
Related information
Windows 10, SDK 10.0.401, and reproduced on main at 3917a24
This bug repros going back at least to SDK 6.0.428. But going from 10.0.202 to 10.0.401, it became more visible as it can affect some usages of Array.init as well. This is how I ran into it.
Activity
#20732 fix (clobbered locals in GenIntegerForLoop) (#20733)