diff options
author | Eric Seidel <gridaphobe@gmail.com> | 2016-04-04 12:05:01 +0200 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2016-04-04 13:05:20 +0200 |
commit | 7407a66d5bd29aa011f5a4228c6e2b2f7f8ad3f8 (patch) | |
tree | a79dbba0a8a0c3a7ecb12e1262487f0d876072c7 /docs | |
parent | 9b6820cdd6bac8b8346be48224627e3feefa9036 (diff) | |
download | haskell-7407a66d5bd29aa011f5a4228c6e2b2f7f8ad3f8.tar.gz |
Don't infer CallStacks
We originally wanted CallStacks to be opt-in, but dealing with let
binders complicated things, forcing us to infer CallStacks. It turns
out that the inference is actually unnecessary though, we can let the
wanted CallStacks bubble up to the outer context by refusing to
quantify over them. Eventually they'll be solved from a given CallStack
or defaulted to the empty CallStack if they reach the top.
So this patch prevents GHC from quantifying over CallStacks, getting us
back to the original plan. There's a small ugliness to do with
PartialTypeSignatures, if the partial theta contains a CallStack
constraint, we *do* want to quantify over the CallStack; the user asked
us to!
Note that this means that
foo :: _ => CallStack
foo = getCallStack callStack
will be an *empty* CallStack, since we won't infer a CallStack for the
hole in the theta. I think this is the right move though, since we want
CallStacks to be opt-in. One can always write
foo :: (HasCallStack, _) => CallStack
foo = getCallStack callStack
to get the CallStack and still have GHC infer the rest of the theta.
Test Plan: ./validate
Reviewers: goldfire, simonpj, austin, hvr, bgamari
Reviewed By: simonpj, bgamari
Subscribers: bitemyapp, thomie
Projects: #ghc
Differential Revision: https://phabricator.haskell.org/D1912
GHC Trac Issues: #11573
Diffstat (limited to 'docs')
-rw-r--r-- | docs/users_guide/glasgow_exts.rst | 50 |
1 files changed, 24 insertions, 26 deletions
diff --git a/docs/users_guide/glasgow_exts.rst b/docs/users_guide/glasgow_exts.rst index 220e642733..0bd48d3b6e 100644 --- a/docs/users_guide/glasgow_exts.rst +++ b/docs/users_guide/glasgow_exts.rst @@ -13367,8 +13367,10 @@ 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``. :: +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``. :: errorWithCallStack :: HasCallStack => String -> a errorWithCallStack msg = error (msg ++ "\n" ++ prettyCallStack callStack) @@ -13386,12 +13388,12 @@ alongside our error message. 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 + myHead :: HasCallStack => [a] -> a + myHead [] = errorWithCallStack "empty" + myHead (x:xs) = x bad :: Int - bad = head [] + bad = myHead [] .. code-block:: none @@ -13399,27 +13401,23 @@ example :: *** 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 + myHead, 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. +includes the call-site of ``errorWithCallStack`` in ``myHead``, and of +``myHead`` in ``bad``, but not the call-site of ``bad`` at the GHCi +prompt. -GHC solves ``HasCallStack`` constraints in three steps: +GHC solves ``HasCallStack`` constraints in two steps: -1. If there is a ``CallStack`` in scope -- i.e. the enclosing function +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. 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). +2. Otherwise GHC will solve the ``HasCallStack`` constraint for the + singleton ``CallStack`` containing just the current call-site. -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. +Importantly, GHC will **never** infer a ``HasCallStack`` constraint, +you must request it explicitly. ``CallStack`` is kept abstract, but GHC provides a function :: @@ -13433,20 +13431,20 @@ package, module, and file name, as well as the line and column numbers. 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 +details. Consider the ``myHead`` 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 + myHead :: HasCallStack => [a] -> a + myHead [] = withFrozenCallStack (errorWithCallStack "empty") + myHead (x:xs) = x .. code-block:: none - ghci> head [] + ghci> myHead [] *** Exception: empty CallStack (from HasCallStack): - head, called at Bad.hs:12:7 in main:Bad + 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 |