summaryrefslogtreecommitdiff
path: root/docs/users_guide
diff options
context:
space:
mode:
authorEric Seidel <gridaphobe@gmail.com>2016-02-01 14:32:19 +0100
committerBen Gamari <ben@smart-cactus.org>2016-02-01 14:32:25 +0100
commit94048f9fb01c541215cfc9cc215af83566b63236 (patch)
treee2407615eaf3b9d2298ebf0c688d04bbb5f40bd2 /docs/users_guide
parent0d601657ca6ec1812492bb16a7d0e181b370e2d8 (diff)
downloadhaskell-94048f9fb01c541215cfc9cc215af83566b63236.tar.gz
Hide the CallStack implicit parameter
The implicit parameter isn't actually very relevant to the CallStack machinery, so we hide the implementation details behind a constraint alias ``` type HasCallStack = (?callStack :: CallStack) ``` This has a few benefits: 1. No need to enable `ImplicitParams` in user code. 2. No need to remember the `?callStack` naming convention. 3. Gives us the option to change the implementation details in the future with less user-land breakage. The revised `CallStack` API is exported from `GHC.Stack` and makes no mention of the implicit parameter. Test Plan: ./validate Reviewers: simonpj, austin, hvr, bgamari Reviewed By: simonpj, bgamari Subscribers: thomie Projects: #ghc Differential Revision: https://phabricator.haskell.org/D1818
Diffstat (limited to 'docs/users_guide')
-rw-r--r--docs/users_guide/8.0.1-notes.rst26
-rw-r--r--docs/users_guide/ghci.rst4
-rw-r--r--docs/users_guide/glasgow_exts.rst186
3 files changed, 122 insertions, 94 deletions
diff --git a/docs/users_guide/8.0.1-notes.rst b/docs/users_guide/8.0.1-notes.rst
index 41e6c2b579..cf4cf8dfae 100644
--- a/docs/users_guide/8.0.1-notes.rst
+++ b/docs/users_guide/8.0.1-notes.rst
@@ -47,8 +47,8 @@ The highlights, since the 7.10 branch, are:
- :ghc-flag:`-XDuplicateRecordFields`, allowing multiple datatypes to declare the same
record field names provided they are used unambiguously (see :ref:`duplicate-record-fields`)
-- Support for implicit parameters providing light-weight
- :ref:`callstacks and source locations <implicit-callstacks>`
+- Support for lightweight
+ :ref:`callstacks and source locations <hascallstack>`
- User-defined error messages for type errors
@@ -85,24 +85,20 @@ Language
-- | Just a normal sum
Sum :: Int -> Int -> Expr Int
-- Implicit parameters of the new ``base`` type :base-ref:`GHC.Stack.CallStack <GHC-Stack.html>`
- are treated specially in function calls, the solver automatically
- appends the source location of the call to the ``CallStack`` in
- the environment. For example ::
+- The new ``base`` constraint :base-ref:`GHC.Stack.HasCallStack <GHC-Stack.html>`
+ can be used by functions to request a partial call-stack. For example ::
- myerror :: (?callStack :: CallStack) => String -> a
- myerror msg = error (msg ++ "\n" ++ prettyCallStack ?callStack)
+ errorWithCallStack :: HasCallStack => String -> a
+ errorWithCallStack msg = error (msg ++ "\n" ++ prettyCallStack callStack)
- ghci> myerror "die"
+ ghci> errorWithCallStack "die"
*** Exception: die
- CallStack (from ImplicitParams):
- myerror, called at <interactive>:2:1 in interactive:Ghci1
+ CallStack (from HasCallStack):
+ errorWithCallStack, called at <interactive>:2:1 in interactive:Ghci1
- prints the call-site of ``myerror``. The name of the implicit
- parameter does not matter, but within ``base`` we call it
- ``?callStack``.
+ prints the call-site of ``errorWithCallStack``.
- See :ref:`lib-base` for a description of the ``CallStack`` type.
+ See :ref:`hascallstack` for a description of ``HasCallStack``.
- GHC now supports visible type application, allowing
programmers to easily specify how type parameters should be
diff --git a/docs/users_guide/ghci.rst b/docs/users_guide/ghci.rst
index c1ef93508f..20afb89d0e 100644
--- a/docs/users_guide/ghci.rst
+++ b/docs/users_guide/ghci.rst
@@ -1136,8 +1136,8 @@ conjunction with ``-fexternal-interpreter``.
There are three ways to get access to the current call stack.
- ``error`` and ``undefined`` automatically attach the current stack
- to the error message. This often complements the implicit stack
- stack (see :ref:`implicit-callstacks`), so both call stacks are
+ to the error message. This often complements the ``HasCallStack``
+ stack (see :ref:`hascallstack`), so both call stacks are
shown.
- ``Debug.Trace.traceStack`` is a version of ``Debug.Trace.trace``
diff --git a/docs/users_guide/glasgow_exts.rst b/docs/users_guide/glasgow_exts.rst
index 6ea2ef65df..c09d0efe6d 100644
--- a/docs/users_guide/glasgow_exts.rst
+++ b/docs/users_guide/glasgow_exts.rst
@@ -8040,83 +8040,6 @@ a type signature for ``y``, then ``y`` will get type
``let`` will see the inner binding of ``?x``, so ``(f 9)`` will return
``14``.
-.. _implicit-callstacks:
-
-Implicit CallStacks
-~~~~~~~~~~~~~~~~~~~
-
-Implicit parameters of the new ``base`` type ``GHC.Stack.CallStack`` are
-treated specially in function calls, the solver automatically pushes
-the source location of the call onto the ``CallStack`` in the
-environment. For example
-
-::
-
- myerror :: (?callStack :: CallStack) => String -> a
- myerror msg = error (msg ++ "\n" ++ prettyCallStack ?callStack)
-
- ghci> myerror "die"
- *** Exception: die
- CallStack (from ImplicitParams):
- myerror, called at <interactive>:2:1 in interactive:Ghci1
-
-prints the call-site of ``myerror``. The name of the implicit
-parameter does not matter, but within ``base`` we call it
-``?callStack``.
-
-The ``CallStack`` will only extend as far as the types allow it, for
-example
-
-.. code-block:: none
-
- head :: (?callStack :: CallStack) => [a] -> a
- head [] = myerror "empty"
- head (x:xs) = x
-
- bad :: Int
- bad = head []
-
- ghci> bad
- *** Exception: empty
- CallStack (from ImplicitParams):
- myerror, called at Bad.hs:8:15 in main:Bad
- head, called at Bad.hs:12:7 in main:Bad
-
-includes the call-site of ``myerror`` in ``head``, and of ``head`` in
-``bad``, but not the call-site of ``bad`` at the GHCi prompt.
-
-GHC will never report an unbound implicit ``CallStack``, and will
-instead default such occurrences to the empty ``CallStack``.
-
-``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 will infer ``CallStack`` constraints using the same rules as for
-ordinary implicit parameters.
-
-``GHC.Stack`` additionally exports a function ``freezeCallStack`` that
-allows users to freeze a ``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 ``head`` example above, the ``myerror`` line in
-the printed stack is not particularly enlightening, so we might choose
-to suppress it by freezing the ``CallStack`` that we pass to ``myerror``.
-
-.. code-block:: none
-
- head :: (?callStack :: CallStack) => [a] -> a
- head [] = let ?callStack = freezeCallStack ?callStack in myerror "empty"
- head (x:xs) = x
-
- ghci> head []]
- *** Exception: empty
- CallStack (from ImplicitParams):
- head, called at Bad.hs:12:7 in main:Bad
-
.. _kinding:
@@ -12879,3 +12802,112 @@ intuitive: ::
let f = /\a \(d::Eq a). fst (member, True) in body
Note that the bang has no effect at all in this case
+
+.. _hascallstack:
+
+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 ::
+
+ errorWithCallStack :: HasCallStack => String -> a
+
+as a variant of ``error`` that will get its call-site. We can access the
+call-stack inside ``errorWithCallStack`` with ``GHC.Stack.callStack``. ::
+
+ errorWithCallStack :: HasCallStack => String -> a
+ errorWithCallStack msg = error (msg ++ "\n" ++ prettyCallStack callStack)
+
+Thus, if we call ``errorWithCallStack`` we will get a formatted call-stack
+alongside our error message.
+
+.. code-block:: none
+
+ ghci> errorWithCallStack "die"
+ *** Exception: die
+ CallStack (from HasCallStack):
+ errorWithCallStack, called at <interactive>:2:1 in interactive:Ghci1
+
+The ``CallStack`` will only extend as far as the types allow it, for
+example ::
+
+ head :: HasCallStack => [a] -> a
+ head [] = errorWithCallStack "empty"
+ head (x:xs) = x
+
+ bad :: Int
+ bad = head []
+
+.. code-block:: none
+
+ ghci> bad
+ *** Exception: empty
+ CallStack (from HasCallStack):
+ errorWithCallStack, called at Bad.hs:8:15 in main:Bad
+ head, called at Bad.hs:12:7 in main:Bad
+
+includes the call-site of ``errorWithCallStack`` in ``head``,
+and of ``head`` in ``bad``,
+but not the call-site of ``bad`` at the GHCi prompt.
+
+GHC solves ``HasCallStack`` constraints in three steps:
+
+1. If there is a ``CallStack`` in scope -- i.e. the enclosing function
+ has a ``HasCallStack`` constraint -- GHC will push the new call-site
+ onto the existing ``CallStack``.
+
+2. If there is no ``CallStack`` in scope -- e.g. in the GHCi session
+ above -- and the enclosing definition does not have an explicit
+ type signature, GHC will infer a ``HasCallStack`` constraint for the
+ enclosing definition (subject to the monomorphism restriction).
+
+3. If there is no ``CallStack`` in scope and the enclosing definition
+ has an explicit type signature, GHC will solve the ``HasCallStack``
+ constraint for the singleton ``CallStack`` containing just the
+ current call-site.
+
+``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 ``head`` example above, the ``errorWithCallStack`` line in
+the printed stack is not particularly enlightening, so we might choose
+to suppress it by freezing the ``CallStack`` that we pass to ``errorWithCallStack``. ::
+
+ head :: HasCallStack => [a] -> a
+ head [] = withFrozenCallStack (errorWithCallStack "empty")
+ head (x:xs) = x
+
+.. code-block:: none
+
+ ghci> head []
+ *** Exception: empty
+ CallStack (from HasCallStack):
+ head, 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.
+
+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.