id	summary	reporter	owner	description	type	status	priority	milestone	component	version	resolution	keywords	cc	os	architecture	failure	difficulty	testcase	blockedby	blocking	related
5129	"""evaluate"" optimized away"	dons	simonmar	"Reported on Stackoverflow: http://stackoverflow.com/questions/5697159/testing-for-error-calls-in-hunit

With optimizations on, the following program, which normally succeeds (correctly generating an exception), instead fails, and the exception is optimized away.

{{{
import Control.Exception
import Test.HUnit

throwIfNegative :: Int -> String
throwIfNegative n | n < 0     = error ""negative""
                  | otherwise = ""no worries""
{-# NOINLINE throwIfNegative #-}

case_negative =
    handleJust errorCalls (const $ return ()) $ do
        evaluate $ throwIfNegative (-1)
        assertFailure ""must throw when given a negative number""
  where errorCalls (ErrorCall _) = Just ()

main = runTestTT $ TestCase case_negative
}}}

Looking at the core, after a few iterations, the call to `throwIfNegative` is dropped as dead code.

Using seq instead of evaluate is happy enough:

{{{
case_negative =
    handleJust errorCalls (const $ return ()) $ do
        throwIfNegative (-1) `seq` assertFailure ""must throw when given a negative number""
  where errorCalls (ErrorCall _) = Just ()
}}}

or a bang pattern:

{{{
case_negative =
    handleJust errorCalls (const $ return ()) $ do
        let !x = throwIfNegative (-1)
        assertFailure ""must throw when given a negative number""
  where errorCalls (ErrorCall _) = Just ()
}}}

Possibly related to #2273"	bug	closed	normal		Compiler	7.0.3	fixed	seq, evaluate	ezyang@…	Unknown/Multiple	Unknown/Multiple	Incorrect result at runtime					
