Quite a while back, Simon Hengel and I put together a proposal[1] for a new feature in GHC. The basic idea is pretty simple: provide a new pragma that could be used like so:
error :: String -> a
errorLoc :: IO Location -> String -> a
{-# REWRITE_WITH_LOCATION error errorLoc #-}
Then all usages of `error` would be converted into calls to `errorLoc` by the compiler, passing in the location information of where the call originated from. Our three intended use cases are:
* Locations for failing test cases in a test framework
* Locations for log messages
* assert/error/undefined
Note that the current behavior of the assert function[2] already includes this kind of approach, but it is a special case hard-coded into the compiler. This proposal essentially generalizes that behavior and makes it available for all functions, whether included with GHC or user-defined.
The proposal spells out some details of this approach, and contrasts with other methods being used today for the same purpose, such as TH and CPP.