summaryrefslogtreecommitdiff
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
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
-rw-r--r--compiler/typecheck/TcEvidence.hs25
-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
-rw-r--r--libraries/base/GHC/Err.hs21
-rw-r--r--libraries/base/GHC/Exception.hs6
-rw-r--r--libraries/base/GHC/Stack.hs31
-rw-r--r--libraries/base/GHC/Stack/Types.hs93
-rw-r--r--testsuite/driver/testlib.py6
9 files changed, 245 insertions, 153 deletions
diff --git a/compiler/typecheck/TcEvidence.hs b/compiler/typecheck/TcEvidence.hs
index 5dfc7ac4e1..f58b73cf7f 100644
--- a/compiler/typecheck/TcEvidence.hs
+++ b/compiler/typecheck/TcEvidence.hs
@@ -527,16 +527,18 @@ Note [Overview of implicit CallStacks]
The goal of CallStack evidence terms is to reify locations
in the program source as runtime values, without any support
from the RTS. We accomplish this by assigning a special meaning
-to implicit parameters of type GHC.Stack.CallStack.
+to constraints of type GHC.Stack.Types.HasCallStack, an alias
-Implicit CallStacks are regular implicit parameters, augmented with two
-extra rules in the constraint solver:
+ type HasCallStack = (?callStack :: CallStack)
+
+Implicit parameters of type GHC.Stack.Types.CallStack (the name is not
+important) are solved in three steps:
1. Occurrences of CallStack IPs are solved directly from the given IP,
just like a regular IP. For example, the occurrence of `?stk` in
error :: (?stk :: CallStack) => String -> a
- error s = raise (ErrorCall (s ++ show ?stk))
+ error s = raise (ErrorCall (s ++ prettyCallStack ?stk))
will be solved for the `?stk` in `error`s context as before.
@@ -604,14 +606,15 @@ in `g`, because `head` did not explicitly request a CallStack.
Important Details:
- GHC should NEVER report an insoluble CallStack constraint.
-- A CallStack (defined in GHC.Stack) is a [(String, SrcLoc)], where the String
- is the name of the binder that is used at the SrcLoc. SrcLoc is defined in
- GHC.SrcLoc and contains the package/module/file name, as well as the full
- source-span. Both CallStack and SrcLoc are kept abstract so only GHC can
- construct new values.
+- A CallStack (defined in GHC.Stack.Types) is a [(String, SrcLoc)],
+ where the String is the name of the binder that is used at the
+ SrcLoc. SrcLoc is also defined in GHC.Stack.Types and contains the
+ package/module/file name, as well as the full source-span. Both
+ CallStack and SrcLoc are kept abstract so only GHC can construct new
+ values.
-- We will automatically solve any wanted CallStack regardless of the name of the
- IP, i.e.
+- We will automatically solve any wanted CallStack regardless of the
+ name of the IP, i.e.
f = show (?stk :: CallStack)
g = show (?loc :: CallStack)
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.
diff --git a/libraries/base/GHC/Err.hs b/libraries/base/GHC/Err.hs
index f786359ba2..88b9c39898 100644
--- a/libraries/base/GHC/Err.hs
+++ b/libraries/base/GHC/Err.hs
@@ -34,25 +34,30 @@ import {-# SOURCE #-} GHC.Exception( errorCallWithCallStackException )
-- | 'error' stops execution and displays an error message.
error :: forall (v :: Levity). forall (a :: TYPE v).
- (?callStack :: CallStack) => [Char] -> a
+ HasCallStack => [Char] -> a
error s = raise# (errorCallWithCallStackException s ?callStack)
+ -- Bleh, we should be using 'GHC.Stack.callStack' instead of
+ -- '?callStack' here, but 'GHC.Stack.callStack' depends on
+ -- 'GHC.Stack.popCallStack', which is partial and depends on
+ -- 'error'.. Do as I say, not as I do.
-- | A variant of 'error' that does not produce a stack trace.
--
-- @since 4.9.0.0
errorWithoutStackTrace :: forall (v :: Levity). forall (a :: TYPE v).
[Char] -> a
-errorWithoutStackTrace s
- = let ?callStack = freezeCallStack ?callStack
- in error s
-{-# NOINLINE errorWithoutStackTrace #-}
+errorWithoutStackTrace s =
+ -- we don't have withFrozenCallStack yet, so we just inline the definition
+ let ?callStack = freezeCallStack emptyCallStack
+ in error s
+
-- Note [Errors in base]
-- ~~~~~~~~~~~~~~~~~~~~~
-- As of base-4.9.0.0, `error` produces a stack trace alongside the
--- error message using the Implicit CallStack machinery. This provides
+-- error message using the HasCallStack machinery. This provides
-- a partial stack trace, containing the call-site of each function
--- with a (?callStack :: CallStack) implicit parameter constraint.
+-- with a HasCallStack constraint.
--
-- In base, however, the only functions that have such constraints are
-- error and undefined, so the stack traces from partial functions in
@@ -70,7 +75,7 @@ errorWithoutStackTrace s
-- messages which are more appropriate to the context in which 'undefined'
-- appears.
undefined :: forall (v :: Levity). forall (a :: TYPE v).
- (?callStack :: CallStack) => a
+ HasCallStack => a
undefined = error "Prelude.undefined"
-- | Used for compiler-generated error message;
diff --git a/libraries/base/GHC/Exception.hs b/libraries/base/GHC/Exception.hs
index 6c579f0372..187ff88e33 100644
--- a/libraries/base/GHC/Exception.hs
+++ b/libraries/base/GHC/Exception.hs
@@ -200,7 +200,7 @@ showCCSStack stk = "CallStack (from -prof):" : map (" " ++) (reverse stk)
-- prettySrcLoc and prettyCallStack are defined here to avoid hs-boot
-- files. See Note [Definition of CallStack]
--- | Pretty print 'SrcLoc'
+-- | Pretty print a 'SrcLoc'.
--
-- @since 4.8.1.0
prettySrcLoc :: SrcLoc -> String
@@ -212,7 +212,7 @@ prettySrcLoc SrcLoc {..}
, srcLocPackage, ":", srcLocModule
]
--- | Pretty print 'CallStack'
+-- | Pretty print a 'CallStack'.
--
-- @since 4.8.1.0
prettyCallStack :: CallStack -> String
@@ -221,7 +221,7 @@ prettyCallStack = intercalate "\n" . prettyCallStackLines
prettyCallStackLines :: CallStack -> [String]
prettyCallStackLines cs = case getCallStack cs of
[] -> []
- stk -> "CallStack (from ImplicitParams):"
+ stk -> "CallStack (from HasCallStack):"
: map ((" " ++) . prettyCallSite) stk
where
prettyCallSite (f, loc) = f ++ ", called at " ++ prettySrcLoc loc
diff --git a/libraries/base/GHC/Stack.hs b/libraries/base/GHC/Stack.hs
index 727910a659..477dcdc505 100644
--- a/libraries/base/GHC/Stack.hs
+++ b/libraries/base/GHC/Stack.hs
@@ -17,14 +17,16 @@
{-# LANGUAGE MagicHash, NoImplicitPrelude, ImplicitParams, RankNTypes #-}
module GHC.Stack (
- -- * Call stacks
+ errorWithStackTrace,
+
+ -- * Profiling call stacks
currentCallStack,
whoCreated,
- errorWithStackTrace,
- -- * Implicit parameter call stacks
- CallStack, emptyCallStack, freezeCallStack, getCallStack, popCallStack,
- prettyCallStack, pushCallStack, withFrozenCallStack,
+ -- * HasCallStack call stacks
+ CallStack, HasCallStack, callStack, emptyCallStack, freezeCallStack,
+ getCallStack, popCallStack, prettyCallStack, pushCallStack,
+ withFrozenCallStack,
-- * Source locations
SrcLoc(..), prettySrcLoc,
@@ -75,16 +77,25 @@ popCallStack stk = case stk of
EmptyCallStack -> errorWithoutStackTrace "popCallStack: empty stack"
PushCallStack _ stk' -> stk'
FreezeCallStack _ -> stk
+{-# INLINE popCallStack #-}
+-- | Return the current 'CallStack'.
+--
+-- Does *not* include the call-site of 'callStack'.
+--
+-- @since 4.9.0.0
+callStack :: HasCallStack => CallStack
+callStack = popCallStack ?callStack
+{-# INLINE callStack #-}
-- | Perform some computation without adding new entries to the 'CallStack'.
--
-- @since 4.9.0.0
-withFrozenCallStack :: (?callStack :: CallStack)
- => ( (?callStack :: CallStack) => a )
+withFrozenCallStack :: HasCallStack
+ => ( HasCallStack => a )
-> a
withFrozenCallStack do_this =
- -- we pop the stack before freezing it to remove
- -- withFrozenCallStack's call-site
- let ?callStack = freezeCallStack (popCallStack ?callStack)
+ -- we pop the stack before freezing it to remove
+ -- withFrozenCallStack's call-site
+ let ?callStack = freezeCallStack (popCallStack callStack)
in do_this
diff --git a/libraries/base/GHC/Stack/Types.hs b/libraries/base/GHC/Stack/Types.hs
index a971f7c86a..fb92522ab5 100644
--- a/libraries/base/GHC/Stack/Types.hs
+++ b/libraries/base/GHC/Stack/Types.hs
@@ -1,4 +1,10 @@
{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE ImplicitParams #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE RankNTypes #-}
+
{-# OPTIONS_HADDOCK hide #-}
-- we hide this module from haddock to enforce GHC.Stack as the main
-- access point.
@@ -13,15 +19,17 @@
-- Stability : internal
-- Portability : non-portable (GHC Extensions)
--
--- type definitions for call-stacks via implicit parameters.
+-- type definitions for implicit call-stacks.
-- Use "GHC.Stack" from the base package instead of importing this
-- module directly.
--
-----------------------------------------------------------------------------
module GHC.Stack.Types (
- -- * Implicit parameter call stacks
- CallStack(..), emptyCallStack, freezeCallStack, getCallStack, pushCallStack,
+ -- * Implicit call stacks
+ CallStack(..), HasCallStack,
+ emptyCallStack, freezeCallStack, getCallStack, pushCallStack,
+
-- * Source locations
SrcLoc(..)
) where
@@ -49,43 +57,75 @@ import GHC.Integer ()
-- Explicit call-stacks built via ImplicitParams
----------------------------------------------------------------------
--- | Implicit @CallStack@s are an alternate method of obtaining the call stack
--- at a given point in the program.
+-- | Request a CallStack.
--
--- GHC has two built-in rules for solving implicit-parameters of type
--- @CallStack@.
+-- NOTE: The implicit parameter @?callStack :: CallStack@ is an
+-- implementation detail and __should not__ be considered part of the
+-- 'CallStack' API, we may decide to change the implementation in the
+-- future.
--
--- 1. If the @CallStack@ occurs in a function call, it appends the
--- source location of the call to the @CallStack@ in the environment.
--- 2. @CallStack@s that cannot be solved normally (i.e. unbound
--- occurrences) are defaulted to the empty @CallStack@.
+-- @since 4.9.0.0
+type HasCallStack = (?callStack :: CallStack)
+
+-- | 'CallStack's are a lightweight method of obtaining a
+-- partial call-stack at any point in the program.
--
--- Otherwise implicit @CallStack@s behave just like ordinary implicit
--- parameters. For example:
+-- A function can request its call-site with the 'HasCallStack' constraint.
+-- For example, we can define
--
-- @
--- myerror :: (?callStack :: CallStack) => String -> a
--- myerror msg = error (msg ++ "\n" ++ prettyCallStack ?callStack)
+-- errorWithCallStack :: HasCallStack => String -> a
-- @
--
--- Will produce the following when evaluated,
+-- as a variant of @error@ that will get its call-site. We can access the
+-- call-stack inside @errorWithCallStack@ with 'GHC.Stack.callStack'.
--
-- @
--- ghci> myerror "die"
--- *** Exception: die
--- CallStack (from ImplicitParams):
--- myerror, called at <interactive>:2:1 in interactive:Ghci1
+-- errorWithCallStack :: HasCallStack => String -> a
+-- errorWithCallStack msg = error (msg ++ "\n" ++ prettyCallStack callStack)
-- @
--
--- @CallStack@s do not interact with the RTS and do not require compilation with
--- @-prof@. On the other hand, as they are built up explicitly using
--- implicit-parameters, they will generally not contain as much information as
--- the simulated call-stacks maintained by the RTS.
+-- Thus, if we call @errorWithCallStack@ we will get a formatted call-stack
+-- alongside our error message.
+--
+--
+-- >>> errorWithCallStack "die"
+-- *** Exception: die
+-- CallStack (from HasCallStack):
+-- errorWithCallStack, called at <interactive>:2:1 in interactive:Ghci1
+--
+--
+-- 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 append the new
+-- call-site to 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).
--
--- A @CallStack@ is a @[(String, SrcLoc)]@. The @String@ is the name of
+-- 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's do not interact with the RTS and do not require compilation
+-- with @-prof@. On the other hand, as they are built up explicitly via the
+-- 'HasCallStack' constraints, they will generally not contain as much
+-- information as the simulated call-stacks maintained by the RTS.
+--
+-- A 'CallStack' is a @[(String, SrcLoc)]@. The @String@ is the name of
-- function that was called, the 'SrcLoc' is the call-site. The list is
-- ordered with the most recently called function at the head.
--
+-- 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.
+--
-- @since 4.8.1.0
data CallStack
= EmptyCallStack
@@ -110,7 +150,7 @@ getCallStack stk = case stk of
-- Note [Definition of CallStack]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--- Implicit CallStacks are defined very early in base because they are
+-- CallStack is defined very early in base because it is
-- used by error and undefined. At this point in the dependency graph,
-- we do not have enough functionality to (conveniently) write a nice
-- pretty-printer for CallStack. The sensible place to define the
@@ -143,6 +183,7 @@ emptyCallStack :: CallStack
emptyCallStack = EmptyCallStack
{-# INLINE emptyCallStack #-}
+
-- | Freeze a call-stack, preventing any further call-sites from being appended.
--
-- prop> pushCallStack callSite (freezeCallStack callStack) = freezeCallStack callStack
diff --git a/testsuite/driver/testlib.py b/testsuite/driver/testlib.py
index 97a5a0d4be..0251884dc4 100644
--- a/testsuite/driver/testlib.py
+++ b/testsuite/driver/testlib.py
@@ -1689,13 +1689,17 @@ def normalise_whitespace( str ):
# Merge contiguous whitespace characters into a single space.
return ' '.join(w for w in str.split())
+callSite_re = re.compile(r', called at (.+):[\d]+:[\d]+ in [\w\-\.]+:')
+
def normalise_callstacks(str):
def repl(matches):
location = matches.group(1)
location = normalise_slashes_(location)
return ', called at {0}:<line>:<column> in <package-id>:'.format(location)
# Ignore line number differences in call stacks (#10834).
- return re.sub(', called at (.+):[\\d]+:[\\d]+ in [\\w\-\.]+:', repl, str)
+ str1 = re.sub(callSite_re, repl, str)
+ # Ignore the change in how we identify implicit call-stacks
+ return str1.replace('from ImplicitParams', 'from HasCallStack')
tyCon_re = re.compile(r'TyCon\s*\d+L?\#\#\s*\d+L?\#\#\s*', flags=re.MULTILINE)