Unexpected strictness (records, exception handling, and -O)
The program below (which is a minimal reproducer, AFAICT), should be equivalent to main = forever $ putStrLn "done"
. Instead, if compiled with -O
(on GHC 8.10.4 or 9.0.1, MacOS), it prints once then crashes with the unused field
error. Without -O
, the correct behaviour is seen.
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE TypeApplications #-}
import Control.Exception
data R = R {field :: ()}
main :: IO a
main = f r0
f :: R -> IO a
f x = do
(\R{} -> handle @E . const $ pure x) x $ do
putStrLn "done"
pure r0
f r0
r0 :: R
r0 = R{field = error "unused field"}
-- it doesn't matter which exception we handle - this could be e.g. type E = IOException
data E = E
deriving (Show, Exception)