Skip to content

Debug.Trace.trace optimized away when throwing exceptions, starting with GHC 8.8

Summary

Debug.Trace.trace messages printed with -O0 are optimized away (e.g. with -O1) in the presence of Control.Exception.throw, starting with GHC 8.8.

Steps to reproduce

Compile and run this with either -O0 or -O1:

import Control.Exception
import Debug.Trace

data MyException = MyException deriving Show
instance Exception MyException

main :: IO ()
main = handle (\ MyException -> putStrLn "Exception") $ do
  trace "Debugging" 5
  `seq` throw MyException
  `seq` putStrLn "Survived Exception"

Expected behavior

I expect the output

Debugging
Exception

which is delivered with -O0 and, up to GHC 8.6, also with -O1. Starting with GHC 8.8 at -O1, it prints only

Exception

Further research

My mental model for Debug.Trace.trace :: String -> a -> a is one of

trace msg a = unsafePerformIO (putStrLn msg) `seq` a

trace msg a = unsafePerformIO $ do
  putStrLn msg
  return a

Both of these actually work, meaning that the debug message is not optimized away for these simple implementations.

Trivium: I found this bug (as I would call it) when researching https://github.com/agda/agda/issues/5379.

Environment

  • GHC versions used: 8.0.2, 8.2.2, 8.4.4, 8.6.4, 8.8.4, 8.10.4, 9.0.1

Optional:

  • Operating System: macOS Mojave 10.14.6
  • System Architecture: Macky McMacFace
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information