Opened 8 years ago

Closed 8 years ago

#5653 closed bug (fixed)

"throw" in IO monad is incorrectly optimized away

Reported by: quark Owned by:
Priority: normal Milestone:
Component: Compiler Version: 6.12.3
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Incorrect result at runtime Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description (last modified by igloo)

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

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!

Attachments (1)

ghcbug.tar.gz (3.5 KB) - added by quark 8 years ago.

Download all attachments as: .zip

Change History (6)

Changed 8 years ago by quark

Attachment: ghcbug.tar.gz added

comment:1 Changed 8 years ago by igloo

Description: modified (diff)

comment:2 Changed 8 years ago by igloo

Resolution: fixed
Status: newclosed

Thanks for the report. This feels very much like some arity bugs that have been fixed, so I think it probably is really fixed. I'll close the ticket, but please reopen if you're not convinced, Simon, and let me know if you'd like me to shrink the testcase.

comment:3 Changed 8 years ago by simonpj

Resolution: fixed
Status: closednew

Perhaps closing is premature, but I agree there is a Good Chance that it's already fixed. Could you try with HEAD and let us know? THANK YOU for reporting.

comment:4 Changed 8 years ago by simonpj

Status: newinfoneeded

comment:5 in reply to:  3 Changed 8 years ago by michalt

Resolution: fixed
Status: infoneededclosed

Replying to simonpj:

Perhaps closing is premature, but I agree there is a Good Chance that it's already fixed. Could you try with HEAD and let us know? THANK YOU for reporting.

I've just compiled the supplied program with HEAD (GHC 7.3.20111125) and it seems you're right:

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

So I'm closing the ticket.

Note: See TracTickets for help on using tickets.