Brian Thanks for reporting this grievous bug. It's now fixed and there's a test in the regression suite for it (cg055). Particular thanks for boiling it down to such a small case.
Simon | -----Original Message----- | From: [EMAIL PROTECTED] [mailto:glasgow-haskell-bugs- | [EMAIL PROTECTED] On Behalf Of Brian Alliet | Sent: 20 January 2005 13:13 | To: glasgow-haskell-bugs@haskell.org | Subject: succ optimization bug with derived Eq and Enum | | GHC 6.2.2 (and a few older 6.2.x versions I tried) seems to improperly | optimize the expression "succ x == y" when using the derived Eq and Enum | instances. Using the data declaration below "isFive Five" will be False. | | data Digit = Zero | One | Two | Three | Four | Five | | Six | Seven | Eight deriving (Eq,Enum) | isFive x = succ x == Six | | This only happens when using the derived Eq and Enum. If either of | them are replaced with a hand written instance everything works fine. It | also has something to do with the number constructors the datatype has. If | there are less than 9 constructors everything works fine. Finally, the bug | only shows up when the -O flag is used. | | Plenty more details (including a self contained test case) are below. | | -Brian | | transam:~/tmp$ cat GHCBug.lhs | \begin{code} | import System (getArgs) | | -- NOTE: When if you remove Eight (or any other constructor) everything works | -- Having at least 9 constructors has something to do with the bug | data Digit = Zero | One | Two | Three | Four | Five | Six | Seven | Eight | deriving (Eq,Enum) | | instance Show Digit where | show Five = "Five" | show Six = "Six" | show _ = undefined | | -- Use either of these instances (instead of derived) and everything works | {-instance Enum Digit where | fromEnum Five = 5 | fromEnum _ = undefined | toEnum 6 = Six | toEnum _ = undefined-} | | {-instance Eq Digit where | Five == Five = True | Six == Six = True | _ == _ = undefined-} | | isFive :: Digit -> Bool | isFive a = succ a == Six | | main :: IO() | main = do | putStrLn ("======") | -- These next two lines are just here to keep ghc from optimizing away stuff | args <- getArgs | let x = if length args == -1 then undefined else Five | putStrLn ("x: " ++ show x) | let y = succ x | putStrLn ("let y = succ x") | putStrLn ("y: " ++ show y) | putStrLn ("y == Six: " ++ show (y == Six)) | putStrLn ("succ x == Six: " ++ show (succ x == Six)) | putStrLn ("isFive x: " ++ show (isFive x)) | \end{code} | transam:~/tmp$ ghc -no-recomp -o GHCBug GHCBug.lhs && ./GHCBug | ====== | x: Five | let y = succ x | y: Six | y == Six: True | succ x == Six: True | isFive x: True | transam:~/tmp$ ghc -O -no-recomp -o GHCBug GHCBug.lhs && ./GHCBug | ====== | x: Five | let y = succ x | y: Six | y == Six: True | succ x == Six: False | isFive x: False | transam:~/tmp$ ghci GHCBug.lhs | ___ ___ _ | / _ \ /\ /\/ __(_) | / /_\// /_/ / / | | GHC Interactive, version 6.2.2, for Haskell 98. | / /_\\/ __ / /___| | http://www.haskell.org/ghc/ | \____/\/ /_/\____/|_| Type :? for help. | | Loading package base ... linking ... done. | Skipping Main ( GHCBug.lhs, GHCBug.o ) | Ok, modules loaded: Main. | Prelude Main> isFive Five | Loading package haskell98 ... linking ... done. | False | Prelude Main> :q | Leaving GHCi. | _______________________________________________ | Glasgow-haskell-bugs mailing list | Glasgow-haskell-bugs@haskell.org | http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs _______________________________________________ Glasgow-haskell-bugs mailing list Glasgow-haskell-bugs@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs