#5775: Inconsistency in demand analysis ---------------------------------+------------------------------------------ Reporter: rl | Owner: Type: bug | Status: new Priority: normal | Milestone: 7.4.2 Component: Compiler | Version: 7.5 Keywords: | Os: Unknown/Multiple Architecture: Unknown/Multiple | Failure: Runtime performance bug Difficulty: Unknown | Testcase: Blockedby: | Blocking: Related: | ---------------------------------+------------------------------------------
Comment(by simonpj): OK I understand what is happening here. Consider this: {{{ f x = do { writeMutVar v 3 ; if x then ... else .. } foo xs = catch (f (head xs)) (\_ -> readMutVar v) }}} Question: can I use call-value for `f`? Is `f` strict in `x`? Well, when you call `f`, it'll certainly evalute `x` (I'm going to ignore the state-token bit here; it's not the point.) But * if you use call-by-value, the the call `foo []` will throw an exception ''before'' executing the `writeMutVar`. * if you use cally-by-need, the call `foo []` will throw an exception only ''after'' executing the `writeMutVar`. The difference is observable. It's even more stark if in instead of `writeMutVar` you have `throwIO`, so that execution should not proceed beyond the `throwIO`. Tickets #148 and #1592 concerned exactly this point. The fix in #148 (''nine'' years ago!) added a grotesque HACK in the demand analyser, commented thus: {{{ -- There's a hack here for I/O operations. Consider -- case foo x s of { (# s, r #) -> y } -- Is this strict in 'y'. Normally yes, but what if 'foo' is an I/O -- operation that simply terminates the program (not in an erroneous way)? -- In that case we should not evaluate y before the call to 'foo'. -- Hackish solution: spot the IO-like situation and add a virtual branch, -- as if we had -- case foo x s of -- (# s, r #) -> y -- other -> return () -- So the 'y' isn't necessarily going to be evaluated -- -- A more complete example (Trac #148, #1592) where this shows up is: -- do { let len = <expensive> ; -- ; when (...) (exitWith ExitSuccess) -- ; print len } }}} Now, Roman has discovered something else. * Not only is the hack unsavory, * not only does it make `loop` lazy when it should be strict, * but in addition it is incredibly fragile. By not-inlining `f` the hack doesn't fire, and `loop` gets stricter! This is simply unacceptable. I don't really know what the right thing to do is. I'm very inclined simply to remove the hack and see whether anyone complains. But I'm open to suggestions. -- Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/5775#comment:4> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler _______________________________________________ Glasgow-haskell-bugs mailing list Glasgow-haskell-bugs@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs