Commit 3ec8288a authored by Eric Seidel's avatar Eric Seidel Committed by Ben Gamari

Rework the Implicit CallStack solver to handle local lets.

We can't just solve CallStack constraints indiscriminately when they
occur in the RHS of a let-binder. The top-level given CallStack (if
any) will not be in scope, so I've re-worked the CallStack solver as
follows:

1. CallStacks are treated like regular IPs unless one of the following
   two rules apply.

2. In a function call, we push the call-site onto a NEW wanted
   CallStack, which GHC will solve as a regular IP (either directly from a
   given, or by quantifying over it in a local let).

3. If, after the constraint solver is done, any wanted CallStacks
   remain, we default them to the empty CallStack. This rule exists mainly
   to clean up after rule 2 in a top-level binder with no given CallStack.

In rule (2) we have to be careful to emit the new wanted with an
IPOccOrigin instead of an OccurrenceOf origin, so rule (2) doesn't fire
again. This is a bit shady but I've updated the Note to explain the
trick.

Test Plan: validate

Reviewers: simonpj, austin, bgamari, hvr

Reviewed By: simonpj, bgamari

Subscribers: thomie

Differential Revision: https://phabricator.haskell.org/D1422

GHC Trac Issues: #10845
parent 1883afb2
......@@ -98,6 +98,7 @@ _darcs/
/docs/users_guide/build-html
/docs/users_guide/build-pdf
/docs/users_guide/.doctrees-*
/docs/users_guide/.doctrees/
/driver/ghci/ghc-pkg-inplace
/driver/ghci/ghci-inplace
/driver/ghci/ghci.res
......
......@@ -1195,6 +1195,5 @@ dsEvCallStack cs = do
let ip_co = unwrapIP (exprType tmExpr)
return (pushCS nameExpr locExpr (mkCastDs tmExpr ip_co))
case cs of
EvCsTop name loc tm -> mkPush name loc tm
EvCsPushCall name loc tm -> mkPush (occNameFS $ getOccName name) loc tm
EvCsEmpty -> panic "Cannot have an empty CallStack"
EvCsEmpty -> return emptyCS
......@@ -394,9 +394,6 @@ data EvCallStack
| EvCsPushCall Name RealSrcSpan EvTerm
-- ^ @EvCsPushCall name loc stk@ represents a call to @name@, occurring at
-- @loc@, in a calling context @stk@.
| EvCsTop FastString RealSrcSpan EvTerm
-- ^ @EvCsTop name loc stk@ represents a use of an implicit parameter
-- @?name@, occurring at @loc@, in a calling context @stk@.
deriving( Data.Data, Data.Typeable )
{-
......@@ -511,57 +508,79 @@ 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. A use of
a CallStack IP, e.g.
to implicit parameters of type GHC.Stack.CallStack.
head [] = error (show (?loc :: CallStack))
head (x:_) = x
Implicit CallStacks are regular implicit parameters, augmented with two
extra rules in the constraint solver:
will be solved with the source location that gave rise to the IP
constraint (here, the use of ?loc). If there is already
a CallStack IP in scope, e.g. passed-in as an argument
1. Occurrences of CallStack IPs are solved directly from the given IP,
just like a regular IP. For example, the occurrence of `?stk` in
head :: (?loc :: CallStack) => [a] -> a
head [] = error (show (?loc :: CallStack))
head (x:_) = x
error :: (?stk :: CallStack) => String -> a
error s = raise (ErrorCall (s ++ show ?stk))
will be solved for the `?stk` in `error`s context as before.
2. In a function call, instead of simply passing the given IP, we first
append the current call-site to it. For example, consider a
call to the callstack-aware `error` above.
undefined :: (?stk :: CallStack) => a
undefined = error "undefined!"
Here we want to take the given `?stk` and append the current
call-site, before passing it to `error`. In essence, we want to
rewrite `error "undefined!"` to
let ?stk = pushCallStack <error's location> ?stk
in error "undefined!"
We achieve this effect by emitting a NEW wanted
we will push the new location onto the CallStack that was passed
in. These two cases are reflected by the EvCallStack evidence
type. In the first case, we will create an evidence term
[W] d :: IP "stk" CallStack
EvCsTop "?loc" <?loc's location> EvCsEmpty
from which we build the evidence term
and in the second we'll have a given constraint
EvCsPushCall "error" <error's location> (EvId d)
[G] d :: IP "loc" CallStack
that we use to solve the call to `error`. The new wanted `d` will
then be solved per rule (1), ie as a regular IP.
in scope, and will create an evidence term
(see TcInteract.interactDict)
EvCsTop "?loc" <?loc's location> d
3. We default any insoluble CallStacks to the empty CallStack. Suppose
`undefined` did not request a CallStack, ie
When we call a function that uses a CallStack IP, e.g.
undefinedNoStk :: a
undefinedNoStk = error "undefined!"
f = head xs
Under the usual IP rules, the new wanted from rule (2) would be
insoluble as there's no given IP from which to solve it, so we
would get an "unbound implicit parameter" error.
we create an evidence term
We don't ever want to emit an insoluble CallStack IP, so we add a
defaulting pass to default any remaining wanted CallStacks to the
empty CallStack with the evidence term
EvCsPushCall "head" <head's location> EvCsEmpty
EvCsEmpty
again pushing onto a given evidence term if one exists.
(see TcSimplify.simpl_top and TcSimplify.defaultCallStacks)
This provides a lightweight mechanism for building up call-stacks
explicitly, but is notably limited by the fact that the stack will
stop at the first function whose type does not include a CallStack IP.
For example, using the above definition of head:
For example, using the above definition of `undefined`:
f :: [a] -> a
f = head
head :: [a] -> a
head [] = undefined
head (x:_) = x
g = head []
g = f []
the resulting CallStack will include the call to `undefined` in `head`
and the call to `error` in `undefined`, but *not* the call to `head`
in `g`, because `head` did not explicitly request a CallStack.
the resulting CallStack will include use of ?loc inside head and
the call to head inside f, but NOT the call to f inside g, because f
did not explicitly request a CallStack.
Important Details:
- GHC should NEVER report an insoluble CallStack constraint.
......@@ -572,21 +591,6 @@ Important Details:
source-span. Both CallStack and SrcLoc are kept abstract so only GHC can
construct new values.
- Consider the use of ?stk in:
head :: (?stk :: CallStack) => [a] -> a
head [] = error (show ?stk)
When solving the use of ?stk we'll have a given
[G] d :: IP "stk" CallStack
in scope. In the interaction phase, GHC would normally solve the use of ?stk
directly from the given, i.e. re-using the dicionary. But this is NOT what we
want! We want to generate a *new* CallStack with ?loc's SrcLoc pushed onto
the given CallStack. So we must take care in TcInteract.interactDict to
prioritize solving wanted CallStacks.
- We will automatically solve any wanted CallStack regardless of the name of the
IP, i.e.
......@@ -600,21 +604,19 @@ Important Details:
head [] = error (show (?stk :: CallStack))
the printed CallStack will NOT include head's call-site. This reflects the
standard scoping rules of implicit-parameters. (See TcInteract.interactDict)
standard scoping rules of implicit-parameters.
- An EvCallStack term desugars to a CoreExpr of type `IP "some str" CallStack`.
The desugarer will need to unwrap the IP newtype before pushing a new
call-site onto a given stack (See DsBinds.dsEvCallStack)
- We only want to intercept constraints that arose due to the use of an IP or a
function call. In particular, we do NOT want to intercept the
- When we emit a new wanted CallStack from rule (2) we set its origin to
`IPOccOrigin ip_name` instead of the original `OccurrenceOf func`
(see TcInteract.interactDict).
(?stk :: CallStack) => [a] -> a
~
(?stk :: CallStack) => [a] -> a
This is a bit shady, but is how we ensure that the new wanted is
solved like a regular IP.
constraint that arises from the ambiguity check on `head`s type signature.
(See TcEvidence.isCallStackIP)
-}
mkEvCast :: EvTerm -> TcCoercion -> EvTerm
......@@ -674,7 +676,6 @@ sccEvBinds bs = stronglyConnCompFromEdgedVertices edges
evVarsOfCallStack :: EvCallStack -> VarSet
evVarsOfCallStack cs = case cs of
EvCsEmpty -> emptyVarSet
EvCsTop _ _ tm -> evVarsOfTerm tm
EvCsPushCall _ _ tm -> evVarsOfTerm tm
evVarsOfTypeable :: EvTypeable -> VarSet
......@@ -763,10 +764,8 @@ instance Outputable EvLit where
instance Outputable EvCallStack where
ppr EvCsEmpty
= ptext (sLit "[]")
ppr (EvCsTop name loc tm)
= angleBrackets (ppr (name,loc)) <+> ptext (sLit ":") <+> ppr tm
ppr (EvCsPushCall name loc tm)
= angleBrackets (ppr (name,loc)) <+> ptext (sLit ":") <+> ppr tm
= ppr (name,loc) <+> ptext (sLit ":") <+> ppr tm
instance Outputable EvTypeable where
ppr (EvTypeableTyCon ts) = ptext (sLit "TC") <+> ppr ts
......
......@@ -1264,8 +1264,6 @@ zonkEvTerm env (EvTypeable ty ev) =
zonkEvTerm env (EvCallStack cs)
= case cs of
EvCsEmpty -> return (EvCallStack cs)
EvCsTop n l tm -> do { tm' <- zonkEvTerm env tm
; return (EvCallStack (EvCsTop n l tm')) }
EvCsPushCall n l tm -> do { tm' <- zonkEvTerm env tm
; return (EvCallStack (EvCsPushCall n l tm')) }
......
......@@ -2,13 +2,15 @@
module TcInteract (
solveSimpleGivens, -- Solves [EvVar],GivenLoc
solveSimpleWanteds -- Solves Cts
solveSimpleWanteds, -- Solves Cts
solveCallStack, -- for use in TcSimplify
) where
#include "HsVersions.h"
import BasicTypes ( infinity, IntWithInf, intGtLimit )
import HsTypes ( hsIPNameFS )
import HsTypes ( HsIPName(..) )
import FastString
import TcCanonical
import TcFlatten
......@@ -21,7 +23,7 @@ import Var
import TcType
import Name
import PrelNames ( knownNatClassName, knownSymbolClassName,
callStackTyConKey, typeableClassName, coercibleTyConKey,
typeableClassName, coercibleTyConKey,
heqTyConKey )
import TysWiredIn ( ipClass, typeNatKind, typeSymbolKind, heqDataCon,
coercibleDataCon )
......@@ -683,24 +685,30 @@ interactIrred _ wi = pprPanic "interactIrred" (ppr wi)
interactDict :: InertCans -> Ct -> TcS (StopOrContinue Ct)
interactDict inerts workItem@(CDictCan { cc_ev = ev_w, cc_class = cls, cc_tyargs = tys })
-- don't ever try to solve CallStack IPs directly from other dicts,
-- we always build new dicts instead.
| isWanted ev_w
, Just ip_name <- isCallStackCt workItem
, OccurrenceOf func <- ctLocOrigin (ctEvLoc ev_w)
-- If we're given a CallStack constraint that arose from a function
-- call, we need to push the current call-site onto the stack instead
-- of solving it directly from a given.
-- See Note [Overview of implicit CallStacks]
| Just mkEvCs <- isCallStackIP loc cls tys
, isWanted ev_w
= do let ev_cs =
case lookupInertDict inerts cls tys of
Just ev | isGiven ev -> mkEvCs (ctEvTerm ev)
_ -> mkEvCs (EvCallStack EvCsEmpty)
-- now we have ev_cs :: CallStack, but the evidence term should
-- be a dictionary, so we have to coerce ev_cs to a
-- dictionary for `IP ip CallStack`
let ip_ty = mkClassPred cls tys
let ev_tm = mkEvCast (EvCallStack ev_cs) (wrapIP ip_ty)
addSolvedDict ev_w cls tys
setWantedEvBind (ctEvId ev_w) ev_tm
stopWith ev_w "Wanted CallStack IP"
= do { let loc = ctEvLoc ev_w
-- First we emit a new constraint that will capture the
-- given CallStack.
; let new_loc = setCtLocOrigin loc (IPOccOrigin (HsIPName ip_name))
-- We change the origin to IPOccOrigin so
-- this rule does not fire again.
-- See Note [Overview of implicit CallStacks]
; mb_new <- newWantedEvVar new_loc (ctEvPred ev_w)
; emitWorkNC (freshGoals [mb_new])
-- Then we solve the wanted by pushing the call-site onto the
-- newly emitted CallStack.
; let ev_cs = EvCsPushCall func (ctLocSpan loc) (getEvTerm mb_new)
; solveCallStack ev_w ev_cs
; stopWith ev_w "Wanted CallStack IP" }
| Just ctev_i <- lookupInertDict inerts cls tys
= do { (inert_effect, stop_now) <- solveOneFromTheOther ctev_i ev_w
......@@ -720,8 +728,6 @@ interactDict inerts workItem@(CDictCan { cc_ev = ev_w, cc_class = cls, cc_tyargs
| otherwise
= do { addFunDepWork inerts ev_w cls
; continueWith workItem }
where
loc = ctEvLoc ev_w
interactDict _ wi = pprPanic "interactDict" (ppr wi)
......@@ -777,25 +783,6 @@ interactGivenIP inerts workItem@(CDictCan { cc_ev = ev, cc_class = cls
interactGivenIP _ wi = pprPanic "interactGivenIP" (ppr wi)
-- | Is the constraint for an implicit CallStack parameter?
-- i.e. (IP "name" CallStack)
isCallStackIP :: CtLoc -> Class -> [Type] -> Maybe (EvTerm -> EvCallStack)
isCallStackIP loc cls tys
| cls == ipClass
, [_ip_name, ty] <- tys
, Just (tc, _) <- splitTyConApp_maybe ty
, tc `hasKey` callStackTyConKey
= occOrigin (ctLocOrigin loc)
| otherwise
= Nothing
where
locSpan = ctLocSpan loc
-- We only want to grab constraints that arose due to the use of an IP or a
-- function call. See Note [Overview of implicit CallStacks]
occOrigin (OccurrenceOf n) = Just (EvCsPushCall n locSpan)
occOrigin (IPOccOrigin n) = Just (EvCsTop ('?' `consFS` hsIPNameFS n) locSpan)
occOrigin _ = Nothing
{-
Note [Shadowing of Implicit Parameters]
......@@ -2102,6 +2089,14 @@ a TypeRep for them. For qualified but not polymorphic types, like
For now we leave it off, until we have a better story for impredicativity.
-}
solveCallStack :: CtEvidence -> EvCallStack -> TcS ()
solveCallStack ev ev_cs = do
-- We're given ev_cs :: CallStack, but the evidence term should be a
-- dictionary, so we have to coerce ev_cs to a dictionary for
-- `IP ip CallStack`. See Note [Overview of implicit CallStacks]
let ev_tm = mkEvCast (EvCallStack ev_cs) (wrapIP (ctEvPred ev))
setWantedEvBind (ctEvId ev) ev_tm
{- ********************************************************************
* *
Class lookup for lifted equality
......
......@@ -67,7 +67,7 @@ module TcRnTypes(
isCDictCan_Maybe, isCFunEqCan_maybe,
isCIrredEvCan, isCNonCanonical, isWantedCt, isDerivedCt,
isGivenCt, isHoleCt, isOutOfScopeCt, isExprHoleCt, isTypeHoleCt,
isUserTypeErrorCt, getUserTypeErrorMsg,
isUserTypeErrorCt, isCallStackCt, getUserTypeErrorMsg,
ctEvidence, ctLoc, setCtLoc, ctPred, ctFlavour, ctEqRel, ctOrigin,
mkTcEqPredLikeEv,
mkNonCanonical, mkNonCanonicalCt,
......@@ -127,6 +127,7 @@ import HsSyn
import CoreSyn
import HscTypes
import TcEvidence
import TysWiredIn ( callStackTyCon, ipClass )
import Type
import CoAxiom ( Role )
import Class ( Class )
......@@ -1731,6 +1732,20 @@ isUserTypeErrorCt ct = case getUserTypeErrorMsg ct of
Just _ -> True
_ -> False
-- | Is the constraint for an Implicit CallStack
-- (i.e. @IP "name" CallStack@)?
--
-- If so, returns @Just "name"@.
isCallStackCt :: Ct -> Maybe FastString
isCallStackCt CDictCan { cc_class = cls, cc_tyargs = tys }
| cls == ipClass
, [ip_name_ty, ty] <- tys
, Just (tc, _) <- splitTyConApp_maybe ty
, tc == callStackTyCon
= isStrLitTy ip_name_ty
isCallStackCt _
= Nothing
instance Outputable Ct where
ppr ct = ppr (cc_ev ct) <+> parens pp_sort
where
......
......@@ -154,7 +154,41 @@ simpl_top wanteds
; if something_happened
then do { wc_residual <- nestTcS (solveWantedsAndDrop wc)
; try_class_defaulting wc_residual }
else return wc }
-- See Note [Overview of implicit CallStacks]
else try_callstack_defaulting wc }
try_callstack_defaulting :: WantedConstraints -> TcS WantedConstraints
try_callstack_defaulting wc
| isEmptyWC wc
= return wc
| otherwise
= defaultCallStacks wc
-- | Default any remaining @CallStack@ constraints to empty @CallStack@s.
defaultCallStacks :: WantedConstraints -> TcS WantedConstraints
-- See Note [Overview of implicit CallStacks]
defaultCallStacks wanteds
= do simples <- handle_simples (wc_simple wanteds)
implics <- mapBagM handle_implic (wc_impl wanteds)
return (wanteds { wc_simple = simples, wc_impl = implics })
where
handle_simples simples
= catBagMaybes <$> mapBagM defaultCallStack simples
handle_implic implic = do
wanteds <- defaultCallStacks (ic_wanted implic)
return (implic { ic_wanted = wanteds })
defaultCallStack ct@(CDictCan { cc_ev = ev_w })
| Just _ <- isCallStackCt ct
= do { solveCallStack ev_w EvCsEmpty
; return Nothing }
defaultCallStack ct
= return (Just ct)
-- | Type-check a thing, returning the result and any EvBinds produced
-- during solving. Emits errors -- but does not fail -- if there is trouble.
......@@ -227,7 +261,7 @@ Option (i) had many disadvantages:
untouchable.
Instead our new defaulting story is to pull defaulting out of the solver loop and
go with option (i), implemented at SimplifyTop. Namely:
go with option (ii), implemented at SimplifyTop. Namely:
- First, have a go at solving the residual constraint of the whole
program
- Try to approximate it with a simple constraint
......
......@@ -113,7 +113,6 @@ import GHC.Fingerprint
import GHC.Show ( showMultiLineString )
#if __GLASGOW_HASKELL__ > 710
import GHC.Stack
import GHC.Exception
#endif
{-
......@@ -1071,8 +1070,8 @@ pprTraceIt desc x = pprTrace desc (ppr x) x
-- | If debug output is on, show some 'SDoc' on the screen along
-- with a call stack when available.
#if __GLASGOW_HASKELL__ > 710
pprSTrace :: (?location :: CallStack) => SDoc -> a -> a
pprSTrace = pprTrace (showCallStack ?location)
pprSTrace :: (?callStack :: CallStack) => SDoc -> a -> a
pprSTrace = pprTrace (prettyCallStack ?callStack)
#else
pprSTrace :: SDoc -> a -> a
pprSTrace = pprTrace "no callstack info"
......
......@@ -31,28 +31,25 @@ Language
-- | Just a normal sum
Sum :: Int -> Int -> Expr Int
- Implicit parameters of the new ghc-prim type ``GHC.Types.CallStack``
are treated specially, and automatically solved for the current
source location. For example
- Implicit parameters of the new ``base`` type ``GHC.Stack.CallStack``
are treated specially in function calls, the solver automatically
appends the source location of the call to the ``CallStack`` in
the environment. For example
::
myerror :: (?callStack :: CallStack) => String -> a
myerror msg = error (msg ++ "\n" ++ prettyCallStack ?callStack)
f = print (?stk :: CallStack)
ghci> myerror "die"
*** Exception: die
CallStack (from ImplicitParams):
myerror, called at <interactive>:2:1 in interactive:Ghci1
will print the singleton stack containing the occurrence of ``?stk``.
If there is another ``CallStack`` implicit in-scope, the new location
will be appended to the existing stack, e.g.
prints the call-site of ``myerror``. The name of the implicit
parameter does not matter, but within ``base`` we call it
``?callStack``.
::
f :: (?stk :: CallStack) => IO ()
f = print (?stk :: CallStack)
will print the occurrence of ``?stk`` and the call-site of ``f``. The
name of the implicit parameter does not matter.
See the release notes for ghc-prim for a description of the
``CallStack`` type.
See :ref:`lib-base` for a description of the ``CallStack`` type.
- To conform to the common case, the default role assigned to
parameters of datatypes declared in ``hs-boot`` files is
......@@ -279,19 +276,22 @@ array
- Version number XXXXX (was 0.5.0.0)
.. _lib-base:
base
~~~~
- Version number 4.9.0.0 (was 4.7.0.0)
- A new module ``GHC.SrcLoc`` was added, exporting a new type
``SrcLoc``. A ``SrcLoc`` contains package, module, and file names, as
well as start and end positions.
- A new type ``CallStack`` was added for use with the new implicit
callstack parameters. A ``CallStack`` is a ``[(String, SrcLoc)]``,
- ``GHC.Stack`` exports two new types ``SrcLoc`` and ``CallStack``. A
``SrcLoc`` contains package, module, and file names, as well as start
and end positions. A ``CallStack`` is a ``[(String, SrcLoc)]``,
sorted by most-recent call.
- ``error`` and ``undefined`` will now report a partial stack-trace
using the new ``CallStack`` feature (and the ``-prof`` stack if available).
- A new function, ``interruptible``, was added to ``GHC.IO`` allowing
an ``IO`` action to be run such that it can be interrupted by an
asynchronous exception, even if exceptions are masked (except if
......
......@@ -8151,37 +8151,46 @@ a type signature for ``y``, then ``y`` will get type
Special implicit parameters
~~~~~~~~~~~~~~~~~~~~~~~~~~~
GHC treats implicit parameters of type ``GHC.Types.CallStack``
specially, by resolving them to the current location in the program.
Consider:
Implicit parameters of the new ``base`` type ``GHC.Stack.CallStack`` are
treated specially in function calls, the solver automatically appends
the source location of the call to the ``CallStack`` in the
environment. For example
::
myerror :: (?callStack :: CallStack) => String -> a
myerror msg = error (msg ++ "\n" ++ prettyCallStack ?callStack)
f :: String
f = show (?loc :: CallStack)
ghci> myerror "die"
*** Exception: die
CallStack (from ImplicitParams):
myerror, called at <interactive>:2:1 in interactive:Ghci1
GHC will automatically resolve ``?loc`` to its source location. If
another implicit parameter with type ``CallStack`` is in scope, GHC will
append the two locations, creating an explicit call-stack. For example:
prints the call-site of ``myerror``. The name of the implicit
parameter does not matter, but within ``base`` we call it
``?callStack``.
::
f :: (?stk :: CallStack) => String
f = show (?stk :: CallStack)
will produce the location of ``?stk``, followed by ``f``\'s call-site.
Note that the name of the implicit parameter does not matter (we used
``?loc`` above), GHC will solve any implicit parameter with the right
type. The name does, however, matter when pushing new locations onto
existing stacks. Consider:
The ``CallStack`` will only extend as far as the types allow it, for
example
::
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
f :: (?stk :: CallStack) => String
f = show (?loc :: CallStack)
includes the call-site of ``myerror`` in ``head``, and of ``head`` in
``bad``, but not the call-site of ``bad`` at the GHCi prompt.
When we call ``f``, the stack will include the use of ``?loc``, but not
the call to ``f``; in this case the names must match.
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
......@@ -8192,15 +8201,9 @@ the call to ``f``; in this case the names must match.
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.
The stack will never be empty, as the first call-site will be the
location at which the implicit parameter was used. GHC will also never
infer ``?loc :: CallStack`` as a type constraint, which means that
functions must explicitly ask to be told about their call-sites.
A potential "gotcha" when using implicit ``CallStack``\ s is that the
``:type`` command in GHCi will not report the ``?loc :: CallStack``
constraint, as the typechecker will immediately solve it. Use ``:info``
instead to print the unsolved type.
GHC will infer ``CallStack`` constraints using the same rules as for
ordinary implicit parameters.
.. _kinding:
......
......@@ -27,9 +27,9 @@ module GHC.Exception
, SomeException(..), ErrorCall(..,ErrorCall), ArithException(..)
, divZeroException, overflowException, ratioZeroDenomException
, errorCallException, errorCallWithCallStackException
, showCallStack, popCallStack, showSrcLoc
-- re-export CallStack and SrcLoc from GHC.Types
, CallStack(..), SrcLoc(..)
, CallStack, getCallStack, prettyCallStack
, SrcLoc(..), prettySrcLoc
) where
import Data.Maybe
......@@ -187,7 +187,7 @@ errorCallWithCallStackException :: String -> CallStack -> SomeException
errorCallWithCallStackException s stk = unsafeDupablePerformIO $ do
ccsStack <- currentCallStack
let
implicitParamCallStack = showCallStackLines (popCallStack stk)
implicitParamCallStack = prettyCallStackLines stk
ccsCallStack = showCCSStack ccsStack
stack = intercalate "\n" $ implicitParamCallStack ++ ccsCallStack
return $ toException (ErrorCallWithLocation s stack)
......@@ -196,11 +196,14 @@ showCCSStack :: [String] -> [String]
showCCSStack [] = []
showCCSStack stk = "CallStack (from -prof):" : map (" " ++) (reverse stk)