
#9390: Inlining prevents evaluation of ignored parts of unboxed tuples -------------------------------------+------------------------------------- Reporter: snoyberg | Owner: Type: bug | Status: merge Priority: normal | Milestone: 7.8.4 Component: Compiler | Version: 7.8.3 Resolution: | Keywords: Operating System: Linux | Architecture: x86_64 (amd64) Type of failure: Incorrect | Difficulty: Unknown result at runtime | Blocked By: Test Case: | Related Tickets: simplCore/should_run/T9390 | Blocking: | Differential Revisions: | -------------------------------------+------------------------------------- Comment (by simonpj): Some quick comments (I'm about to go on holiday): * You shouldn't have to quote the documentation for `pseq` to understand `seq`. If `seq`'s documentation is inadequate, let's fix it. * You say "seq ensures that both one and one + two will be evaluated before the seq expression is evaluated". I would rather say "...before the result of the seq expression is ''returned''". * "We can get the same guaranteed ordering of evaluation by having a function which is only strict in one of its arguments". Definitely not! GHC will inline `add` and all will be lost. Only `pseq` guarantees this behaviour. * Passage starting "This looks like it should be straightforward". Alas you have found yet another dark corner. Here is a comment from the demand analyser: {{{ -- Note [IO hack in the demand analyser] -- -- 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 } }}} You can look at the tickets mentioned for some more background. I hate the hack, but the bottom line is that no, GHC does not (and I think should not) evaluate helper2 before running helper1. That's as far as I got. Thanks for writing this -- it's a good forcing function. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9390#comment:22 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler