diff options
author | Alp Mestanogullari <alp@well-typed.com> | 2018-01-21 12:07:58 -0500 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2018-01-21 12:07:59 -0500 |
commit | 5edb18a962cbfee0ff869b1a77ebf2cd79dd8ef5 (patch) | |
tree | c28b8eede49f6d4721e7009391c4e72bbb22aa24 /docs | |
parent | 0074a08ea9dfd1416aa57a9504be73dcdf7a1e2b (diff) | |
download | haskell-5edb18a962cbfee0ff869b1a77ebf2cd79dd8ef5.tar.gz |
tentative improvement to callstack docs
This is an attempt at clarifying the docs for HasCallStack in both the
user guide and libraries/base/GHC/Stack/Types.hs. The example used right
now is built around an hypothetical 'error' function that doesn't itself
print call stacks, and the fact that this doesn't hold makes it all
confusing, see #14635.
Reviewers: hvr, bgamari
Reviewed By: bgamari
Subscribers: rwbarton, thomie, carter
GHC Trac Issues: #14635
Differential Revision: https://phabricator.haskell.org/D4317
Diffstat (limited to 'docs')
-rw-r--r-- | docs/users_guide/glasgow_exts.rst | 67 |
1 files changed, 53 insertions, 14 deletions
diff --git a/docs/users_guide/glasgow_exts.rst b/docs/users_guide/glasgow_exts.rst index 34efbfd3e2..4125c33b24 100644 --- a/docs/users_guide/glasgow_exts.rst +++ b/docs/users_guide/glasgow_exts.rst @@ -14958,28 +14958,67 @@ 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. -For example, we can define :: +A function can request its call-site with the ``HasCallStack`` constraint +and access it as a Haskell value by using ``callStack``. - errorWithCallStack :: HasCallStack => String -> a +One can then use functions from ``GHC.Stack`` to inspect or pretty +print (as is done in ``f`` below) the call stack. -as a variant of ``error`` that will get its call-site (as of GHC 8.0, -``error`` already gets its call-site, but let's assume for the sake of -demonstration that it does not). We can access the call-stack inside -``errorWithCallStack`` with ``GHC.Stack.callStack``. :: + f :: HasCallStack => IO () + f = putStrLn (prettyCallStack callStack) - errorWithCallStack :: HasCallStack => String -> a - errorWithCallStack msg = error (msg ++ "\n" ++ prettyCallStack callStack) + g :: HasCallStack => IO () + g = f -Thus, if we call ``errorWithCallStack`` we will get a formatted call-stack -alongside our error message. +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``. .. code-block:: none - ghci> errorWithCallStack "die" - *** Exception: die + ghci> f CallStack (from HasCallStack): - errorWithCallStack, called at <interactive>:2:1 in interactive:Ghci1 + 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: + +.. code-block:: none + + 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 + +.. code-block:: none + + 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 :: |