Ticket #1265 (closed bug: fixed)

Opened 6 years ago

Last modified 5 years ago

Template Haskell fail Messages not Getting Through

Reported by: twhitehe@… Owned by: igloo
Priority: normal Milestone: 6.8.1
Component: Template Haskell Version: 6.6
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Difficulty: Unknown
Test Case: Blocked By:
Blocking: Related Tickets:

Description

There is (I believe) a mistake in GHC's template Haskell implementation int the way the fail member is handled. The error messages get eaten and replaced with a cryptic reference to an "IOEnv failure". For example (at the "ghci -fth" prompt):

Prelude> let doit = fail "Code not written yet" :: Language.Haskell.TH.ExpQ
Loading package template-haskell ... linking ... done.
Prelude> $(doit)

<interactive>:1:2:
    Exception when trying to run compile-time code:
      user error (IOEnv failure)
      Code: doit
    In the expression: $[splice]doit
    In the definition of `it': it = $[splice]doit
Prelude>

The problem seems to be that GHC runs the template code in the IOEnv monad (compiler/typecheck/TcSplite.lhs) whose fail implementation (compiler/utils/IOEnv.hs) eats its argument and instead raises "userError "IOEnv failure"".

I put a patch together for this, and will submit it soon (i.e., as soon as I finish reading the pages on how to do so). With the patch, the above examples becomes:

Prelude> let doit = fail "Code not written yet" :: Language.Haskell.TH.ExpQ
Loading package template-haskell ... linking ... done.
Prelude> $(doit)

<interactive>:1:2: Code not written yet
Prelude>

This is achieved through changing the fail implementation for the Q monad to first log the message with report before passing control through the fail member of the underlying Quasi instance (IOEnv in this case) and changing the exception handling code around the running of the template code to gracefully handle exceptions raised in such a manner (i.e., print out the logged message).

It is a bit hackish, but it was the only way I could see to do this with out changing the fail implementation for IOEnv (I assume it was written the way it is for a reason -- possibly to avoid spamming the user with messages regarding compiler problems -- although it does seems strange) or introducing an additional function into the Q monad (such as giveUp from "Notes on Template Haskell Version 2").

Change History

Changed 6 years ago by igloo

  • milestone set to 6.8

It does seem odd that the error string is deliberately ignored (a comment even says that it should be ignored). Anyone know why that is?

Changed 6 years ago by twhitehe@…

I sent the aforementioned patches to the cvs-ghc mailing list (i.e., the ones that achieve the desired result through changing the fail implementation for the Q monad to first log the message and the associated exception handling code).

However, I wanted to note that, with regard to IOEnv eating the fail messages, I grepped the source code for fail, looked at the context of all the uses, and found no explicit uses of IOEnv's fail. By my understanding, that leaves possible pattern match failures on <- in a do as the only use of IOEnv's fail outside of TH code.

Perhaps IOEnv's fail should be changed to not eat the message?

Changed 6 years ago by simonpj

  • owner set to igloo

I think IOEnv eats the message because the typechecker (for example) often does fail, having stuffed its error message in the bag of errors. We don't want an additional message from the fail; the purpose of the fail is just to propagate an exception out to the recovery point if any.

Maybe there's another way to do this. But meanwhile, the bug is fixed. Now you get

Prelude> let doit = fail "Code not written yet" ::Language.Haskell.TH.ExpQ
Loading package template-haskell ... linking ... done.
Prelude> $(doit)

<interactive>:1:2: Code not written yet
Prelude> 

I'm leaving the bug open but assigned to Ian, in the hope that he'll add a test case and then close it.

Simon

Changed 6 years ago by igloo

  • status changed from new to closed
  • resolution set to fixed

It turns out we already have a test case TH_fail:

Tue Apr 10 15:06:53 BST 2007  Tyson Whitehead <twhitehe@uwo.ca>
  * Add a test for use of fail for trac #1265

Changed 6 years ago by igloo

  • milestone changed from 6.8 branch to 6.8.1

Changed 5 years ago by simonmar

  • architecture changed from Unknown to Unknown/Multiple

Changed 5 years ago by simonmar

  • os changed from Unknown to Unknown/Multiple
Note: See TracTickets for help on using tickets.