Skip to content

Expose srcLoc from the assertion architecture to allow better error messages

Assertions give great error messages by including file name and line, but they are disabled for optimisation. While there is a compiler flag to turn them on even in presence of optimisation, this is an awkward external way to simply attach a useful error location to something like error.

It would be great if we could decouple getting the current srcLoc from assertions, and making it available for good error messages.

It is currently possible to do this using TemplateHaskell (e.g. the placeholders package) or CPP, but both are inconvenient for technical reasons (such as breaking tooling) and do not enjoy widespread use.

It seems a shame that the architecture for annotated error messages is already there, but only available through a mechanism that is disabled for optimisation (or at least "intended" to be disabled for optimisation).

Notably, we have the same architecture available for pattern mach failures:

f x | x > 0 = "foo"

main = putStrLn (f (-1)) -- gives srcLoc'd pattern match error message
f x | x > 0 = "foo"
f _         = error "f needs a positive number"

main = putStrLn (f (-1)) -- does not give a srcLoc'd error message

It seems non-sensical that your try to write a better error message (here using error) yields in fact a less-helpful error message.

I completely agree that one can aid bug-fixing by writing globally unique arguments to error or using TH, but from an engineering perspective, a little bit of help from the language/compiler side can improve the situation a lot, and in other languages this is acknowledged and used to everybody's benefit.

There are some alternatives we might consider, such as

  • exposing srcLoc :: String that gives an assert-style location at the lexical position of its occurrence
  • adding an error-like function that behaves like error but also prints a source location

Arguably srcLoc :: String breaks equational reasoning on the syntactic level, as let x = srcLoc in (x, x) and (srcLoc, srcLoc) have different values. However, looking at it from a program execution point of view, referential transparency is preserved since once compiled, any function using srcLoc will always return the same location.

I believe that offering some kind of improvement over the dreaded error or Prelude: undefined should be easy to implement, but let's hear what the people who actually know the compiler think about it.

Trac metadata
Trac field Value
Version 7.8.2
Type FeatureRequest
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information