[GHC] #10246: Literal Pattern match loses order
#10246: Literal Pattern match loses order -------------------------------------+------------------------------------- Reporter: nomeata | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.1 Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: None/Unknown Unknown/Multiple | Blocked By: Test Case: | Related Tickets: Blocking: | Differential Revisions: | -------------------------------------+------------------------------------- I found this long-standing bug while investigating #10245: 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. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10246> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10246: Literal Pattern match loses order -------------------------------------+------------------------------------- Reporter: nomeata | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by Joachim Breitner <mail@…>): In [changeset:"8f0709249826dd2eda9bf53be89f176a4f30c81f/ghc"]: {{{ #!CommitTicketReference repository="ghc" revision="8f0709249826dd2eda9bf53be89f176a4f30c81f" Test case for #10246 still marked known_broken. This also adds the test case for #10245, which should pass once #10246 is fixed. }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10246#comment:1> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10246: Literal Pattern match loses order -------------------------------------+------------------------------------- Reporter: nomeata | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Changes (by nomeata): * cc: rwbarton, simonmar (added) Comment: Currently, the above code will produce {{{ ghc-stage2: panic! (the 'impossible' happened) (GHC version 7.11.20150403 for x86_64-unknown-linux): ASSERT failed! file compiler/basicTypes/Literal.hs line 220 18446744073709551616 }}} Maybe that is a hint as to where this needs to be fixed? Maybe {{{ mkMachInt :: DynFlags -> Integer -> Literal mkMachInt dflags x = ASSERT2( inIntRange dflags x, integer x ) MachInt x }}} is where the clamping to the range of the machine integers should happen? Can we always deduce that from the `dflags`? -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10246#comment:2> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10246: Literal Pattern match loses order -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Changes (by nomeata): * owner: => nomeata Comment: Or maybe the problem is the part of the code that changes the patter {{{ 0x10000000000000000 -> "foo" }}} to {{{ I# 0x10000000000000000# -> "foo" }}} which would be `tidyNPat` in `MatchLit.hs`. Unfortunately, that is far way from the nearest `dflags`. Maybe `hsLitKey :: DynFlags -> HsLit -> Literal` is a good spot for making sure the literal is in range... that seems to work. I’ll shortly open a DR with some questions to those in the know in these matters. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10246#comment:3> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10246: Literal Pattern match loses order -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: bug | Status: patch Priority: normal | Milestone: Component: Compiler | Version: 7.10.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: Phab:D810 -------------------------------------+------------------------------------- Changes (by nomeata): * status: new => patch * differential: => Phab:D810 Comment: See Phab:D810 for a possible fix. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10246#comment:4> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10246: Literal Pattern match loses order -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: bug | Status: patch Priority: normal | Milestone: Component: Compiler | Version: 7.10.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: None/Unknown | Unknown/Multiple Blocked By: | Test Case: Related Tickets: #9533 | Blocking: | Differential Revisions: Phab:D810 -------------------------------------+------------------------------------- Changes (by nomeata): * related: => #9533 Comment: Has come up before: #9533. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10246#comment:5> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10246: Literal Pattern match loses order -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: bug | Status: patch Priority: normal | Milestone: Component: Compiler | Version: 7.10.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #9533 | Differential Rev(s): Phab:D810 -------------------------------------+------------------------------------- Comment (by Ben Gamari <ben@…>): In [changeset:"6dfc5ebf70df8f0fdccc5004d914b777f21f3b72/ghc" 6dfc5eb/ghc]: {{{ #!CommitTicketReference repository="ghc" revision="6dfc5ebf70df8f0fdccc5004d914b777f21f3b72" Ensure that Literals are in range This commit fixes several bugs related to case expressions involving numeric literals which are not in the range of values of their (fixed-width, integral) type. There is a new invariant on Literal: The argument of a MachInt[64] or MachWord[64] must lie within the range of the corresponding primitive type Int[64]# or Word[64]#, as defined by the target machine. This invariant is enforced in mkMachInt[64]/mkMachWord[64] by wrapping the argument to the target type's range if necessary. Test Plan: Test Plan: make slowtest TEST="T9533 T9533b T9533c T10245 T10246" Trac issues: #9533, #10245, #10246, #13171 Reviewers: simonmar, simonpj, austin, bgamari, nomeata Reviewed By: bgamari Subscribers: thomie, rwbarton Differential Revision: https://phabricator.haskell.org/D810 }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10246#comment:6> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#10246: Literal Pattern match loses order -------------------------------------+------------------------------------- Reporter: nomeata | Owner: nomeata Type: bug | Status: closed Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 7.10.1 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #9533 | Differential Rev(s): Phab:D810 Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * status: patch => closed * resolution: => fixed * milestone: => 8.2.1 Old description:
I found this long-standing bug while investigating #10245:
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.
New description: I found this long-standing bug while investigating #10245: Consider this code: {{{#!hs 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. -- -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10246#comment:7> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
participants (1)
-
GHC