#5653: "throw" in IO monad is incorrectly optimized away
---------------------------------+------------------------------------------
    Reporter:  quark             |       Owner:                             
        Type:  bug               |      Status:  new                        
    Priority:  normal            |   Component:  Compiler                   
     Version:  6.12.3            |    Keywords:                             
    Testcase:                    |   Blockedby:                             
          Os:  Unknown/Multiple  |    Blocking:                             
Architecture:  Unknown/Multiple  |     Failure:  Incorrect result at runtime
---------------------------------+------------------------------------------
 In this example program, if I set things up just right, GHC will
 incorrectly execute a function on the IO monad.   I can get GHC to execute
 it properly by removing an unnecessary Id from the export list (!!), by
 removing some complexity in the function (removing if-stmts, for example),
 or by inserting a trace statement.

 On Linux machines (both 32-bit and 64-bit): This bug occurs with GHC
 6.12.3 and 6.12.1.  It does not occur with 6.8.2 or with 7, but I do not
 know if this is because the bug was fixed or perhaps the bug is not
 triggered.  Therefore, I'm attaching this example, so that you can
 identify the source of the bug, and then judge whether it still exists in
 GHC 7.

 I have tested on Mac OS X with GHC 6.10.4 and the bug does not occur
 there.

 In the attached tar-ball, just type "make" and it will build the
 executable "Main" from "Main.hs".  This program calls an IO monad function
 in "Wrap.hs", which has several execution paths through it, but one path
 throws an error, using a function in "Error.hs" (and this is the path that
 "Main" stimulates).  The other files are for data types used by "Wrap".  I
 have attempted to reduce these files to only what is needed.  Note that
 the "Id" type needs to use SpeedyString, or else the bug isn't triggered.

 When you run "Main", you get this:

    # ./Main
    Num elements before (expect 1): 1
    Num elements after (expect 1): 0
    IF YOU SEE THIS MESSAGE, GHC HAS A BUG

 In "addWrap", the first trace shows that the list "is" has one element.
 When we "concatMapM" over the list, it should still have one element.
 There is no branch that would produce zero elements, and yet that's what
 GHC did!  If GHC had properly executed the monad statements, then the call
 to "err" would have thrown an error, looking like this:

    # ./Main
    Num elements before (expect 1): 1
    Main: Normal user error

 You can get GHC to produce this correct behavior in several ways.  One is
 to uncomment (and thus add in) the trace statement right before the call
 to "err":

    traceM("reached error")

 Another way to get the correct behavior is to remove the export of
 "unsafeMessageExit" from "Error.hs"!  How odd!  That function is not used
 anywhere, but maybe it's existence adds more users of "throw" which
 changes GHC's use analysis or something?

 And, of course, you can prevent the bug by simplifying the program in
 various ways.  Removing some if-expressions or case-expressions from
 "Wrap" will do it.  Note that even just leaving in if-expressions that
 have the same value in both arms (such as the definition of "r_ctxs") will
 trigger the bug!

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/5653>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler

_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs

Reply via email to