6.19.5. HasCallStack — Glasgow Haskell Compiler 9.10.0.20240426 User's Guide

# 6.19.5. HasCallStack

`GHC.Stack.HasCallStack` is a lightweight method of obtaining a partial call-stack at any point in the program.

A function can request its call-site with the `HasCallStack` constraint and access it as a Haskell value by using `callStack`.

One can then use functions from `GHC.Stack` to inspect or pretty print (as is done in `f` below) the call stack.

    f :: HasCallStack => IO ()
    f = putStrLn (prettyCallStack callStack)

    g :: HasCallStack => IO ()
    g = f

Evaluating `f` directly shows a call stack with a single entry, while evaluating `g`, which also requests its call-site, shows two entries, one for each computation “annotated” with `HasCallStack`.

    ghci> f
    CallStack (from HasCallStack):
      f, called at <interactive>:19:1 in interactive:Ghci1
    ghci> g
    CallStack (from HasCallStack):
      f, called at <interactive>:17:5 in main:Main
      g, called at <interactive>:20:1 in interactive:Ghci2

The `error` function from the Prelude supports printing the call stack that led to the error in addition to the usual error message:

    ghci> error "bad"
    *** Exception: bad
    CallStack (from HasCallStack):
      error, called at <interactive>:25:1 in interactive:Ghci5

The call stack here consists of a single entry, pinpointing the source of the call to `error`. However, by annotating several computations with `HasCallStack`, figuring out the exact circumstances and sequences of calls that lead to a call to `error` becomes a lot easier, as demonstrated with the simple example below.

    f :: HasCallStack => IO ()
    f = error "bad bad bad"

    g :: HasCallStack => IO ()
    g = f

    h :: HasCallStack => IO ()
    h = g

    ghci> h
    *** Exception: bad bad bad
    CallStack (from HasCallStack):
      error, called at call-stack.hs:4:5 in main:Main
      f, called at call-stack.hs:7:5 in main:Main
      g, called at call-stack.hs:10:5 in main:Main
      h, called at <interactive>:28:1 in interactive:Ghci1

The `CallStack` will only extend as far as the types allow it, for example

    myHead :: HasCallStack => [a] -> a
    myHead []     = error "empty"
    myHead (x:xs) = x

    bad :: Int
    bad = myHead []

    ghci> bad
    *** Exception: empty
    CallStack (from HasCallStack):
      error, called at Bad.hs:8:15 in main:Bad
      myHead, called at Bad.hs:12:7 in main:Bad

includes the call-site of `error` in `myHead`, and of `myHead` in `bad`, but not the call-site of `bad` at the GHCi prompt.

GHC solves `HasCallStack` constraints in two steps:

1. If there is a `CallStack` in scope – i.e. the enclosing definition has a `HasCallStack` constraint – GHC will push the new call-site onto the existing `CallStack`.
2. Otherwise GHC will solve the `HasCallStack` constraint for the singleton `CallStack` containing just the current call-site.

Importantly, GHC will never infer a `HasCallStack` constraint, you must request it explicitly.

`CallStack` is kept abstract, but GHC provides a function

    getCallStack :: CallStack -> [(String, SrcLoc)]

to access the individual call-sites in the stack. The `String` is the name of the function that was called, and the `SrcLoc` provides the package, module, and file name, as well as the line and column numbers.

`GHC.Stack` additionally exports a function `withFrozenCallStack` that allows users to freeze the current `CallStack`, preventing any future push operations from having an effect. This can be used by library authors to prevent `CallStack`s from exposing unnecessary implementation details. Consider the `myHead` example above, the `error` line in the printed stack is not particularly enlightening, so we might choose to suppress it by freezing the `CallStack` that we pass to `error`.

    myHead :: HasCallStack => [a] -> a
    myHead []     = withFrozenCallStack (error "empty")
    myHead (x:xs) = x

    ghci> myHead []
    *** Exception: empty
    CallStack (from HasCallStack):
      myHead, called at Bad.hs:12:7 in main:Bad

NOTE: The intrepid user may notice that `HasCallStack` is just an alias for an implicit parameter `?callStack :: CallStack`. This is an implementation detail and should not be considered part of the `CallStack` API, we may decide to change the implementation in the future.

## 6.19.5.1. Compared with other sources of stack traces

`HasCallStack` does not interact with the RTS and does not require compilation with `-prof`. On the other hand, as the `CallStack` is built up explicitly via the `HasCallStack` constraints, it will generally not contain as much information as the simulated call-stacks maintained by the RTS.