Literal Pattern match loses order
I found this long-standing bug while investigating #10245 (closed):
Consider this code:
f1 :: Int -> String
f1 n = case n of
0 -> "bar"
0x10000000000000000 -> "foo"
_ -> "c"
{-# NOINLINE f1 #-}
g1 :: Int -> String
g1 n = if n == 0 then "bar" else
if n == 0x10000000000000000 then "foo" else
"c"
{-# NOINLINE g1 #-}
f2 :: Int -> String
f2 n = case n of
0x10000000000000000 -> "foo"
0 -> "bar"
_ -> "c"
{-# NOINLINE f2 #-}
g2 :: Int -> String
g2 n = if n == 0x10000000000000000 then "foo" else
if n == 0 then "bar" else
"c"
{-# NOINLINE g2 #-}
main = do
let i = read "0" :: Int
print (f1 i)
print (g1 i)
print (f2 i)
print (g2 i)
According to the report, f1
should behave like g1
and f2
should behave like g2
. But that is not the case: I get
"foo"
"bar"
"foo"
"foo"
The reason is that the branches are sorted, to create fancy code for it, but this does not take into account that 0x10000000000000000 = 0
, at least for Int
.
This bug is present also in 7.8.4, and not (directly) related to my CmmSwitch code: It can also be observed with interpreted code, so the fix must happen earlier.