#5653: "throw" in IO monad is incorrectly optimized away
---------------------------------+------------------------------------------
    Reporter:  quark             |        Owner:                             
        Type:  bug               |       Status:  new                        
    Priority:  normal            |    Milestone:                             
   Component:  Compiler          |      Version:  6.12.3                     
    Keywords:                    |     Testcase:                             
   Blockedby:                    |   Difficulty:                             
          Os:  Unknown/Multiple  |     Blocking:                             
Architecture:  Unknown/Multiple  |      Failure:  Incorrect result at runtime
---------------------------------+------------------------------------------
Description changed by igloo:

Old description:

> 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!

New description:

 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#comment:1>
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