Allow CallStacks to be frozen
authorEric Seidel <gridaphobe@gmail.com>
Wed, 23 Dec 2015 09:10:04 +0000 (10:10 +0100)
committerBen Gamari <ben@smart-cactus.org>
Wed, 23 Dec 2015 10:30:42 +0000 (11:30 +0100)
commit380b25ea4754c2aea683538ffdb179f8946219a0
tree722784415e0f1b29a46fc115baff56f3495c0c9b
parent78248702b0b8189d73f08c89d86f5cb7a3c6ae8c
Allow CallStacks to be frozen

This introduces "freezing," an operation which prevents further
locations from being appended to a CallStack.  Library authors may want
to prevent CallStacks from exposing implementation details, as a matter
of hygiene. For example, in

```
head [] = error "head: empty list"

ghci> head []
*** Exception: head: empty list
CallStack (from implicit params):
  error, called at ...
```

including the call-site of `error` in `head` is not strictly necessary
as the error message already specifies clearly where the error came
from.

So we add a function `freezeCallStack` that wraps an existing CallStack,
preventing further call-sites from being pushed onto it. In other words,

```
pushCallStack callSite (freezeCallStack callStack) = freezeCallStack callStack
```

Now we can define `head` to not produce a CallStack at all

```
head [] =
  let ?callStack = freezeCallStack emptyCallStack
  in error "head: empty list"

ghci> head []
*** Exception: head: empty list
CallStack (from implicit params):
  error, called at ...
```

---

1. We add the `freezeCallStack` and `emptyCallStack` and update the
   definition of `CallStack` to support this functionality.

2. We add `errorWithoutStackTrace`, a variant of `error` that does not
   produce a stack trace, using this feature. I think this is a sensible
   wrapper function to provide in case users want it.

3. We replace uses of `error` in base with `errorWithoutStackTrace`. The
   rationale is that base does not export any functions that use CallStacks
   (except for `error` and `undefined`) so there's no way for the stack
   traces (from Implicit CallStacks) to include user-defined functions.
   They'll only contain the call to `error` itself. As base already has a
   good habit of providing useful error messages that name the triggering
   function, the stack trace really just adds noise to the error. (I don't
   have a strong opinion on whether we should include this third commit,
   but the change was very mechanical so I thought I'd include it anyway in
   case there's interest)

4. Updates tests in `array` and `stm` submodules

Test Plan: ./validate, new test is T11049

Reviewers: simonpj, nomeata, goldfire, austin, hvr, bgamari

Reviewed By: simonpj

Subscribers: thomie

Projects: #ghc

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

GHC Trac Issues: #11049
83 files changed:
compiler/deSugar/DsBinds.hs
compiler/prelude/PrelNames.hs
docs/users_guide/7.12.1-notes.rst
docs/users_guide/glasgow_exts.rst
libraries/array
libraries/base/Control/Concurrent.hs
libraries/base/Control/Exception/Base.hs
libraries/base/Control/Monad/Fix.hs
libraries/base/Control/Monad/ST/Lazy/Imp.hs
libraries/base/Data/Bits.hs
libraries/base/Data/Char.hs
libraries/base/Data/Data.hs
libraries/base/Data/Dynamic.hs
libraries/base/Data/Foldable.hs
libraries/base/Data/List/NonEmpty.hs
libraries/base/Data/Maybe.hs
libraries/base/Data/OldList.hs
libraries/base/Data/Proxy.hs
libraries/base/Data/Semigroup.hs
libraries/base/Data/Type/Coercion.hs
libraries/base/Data/Type/Equality.hs
libraries/base/GHC/Arr.hs
libraries/base/GHC/Base.hs
libraries/base/GHC/Char.hs
libraries/base/GHC/Conc/IO.hs
libraries/base/GHC/Conc/Signal.hs
libraries/base/GHC/Conc/Sync.hs
libraries/base/GHC/Conc/Windows.hs
libraries/base/GHC/ConsoleHandler.hs
libraries/base/GHC/Enum.hs
libraries/base/GHC/Err.hs
libraries/base/GHC/Event/Array.hs
libraries/base/GHC/Event/Control.hs
libraries/base/GHC/Event/EPoll.hsc
libraries/base/GHC/Event/KQueue.hsc
libraries/base/GHC/Event/Manager.hs
libraries/base/GHC/Event/PSQ.hs
libraries/base/GHC/Event/Poll.hsc
libraries/base/GHC/Event/TimerManager.hs
libraries/base/GHC/Exts.hs
libraries/base/GHC/Fingerprint.hs
libraries/base/GHC/Float.hs
libraries/base/GHC/ForeignPtr.hs
libraries/base/GHC/IO/Buffer.hs
libraries/base/GHC/IO/Encoding/CodePage/API.hs
libraries/base/GHC/IO/Handle.hs
libraries/base/GHC/IO/Handle/Internals.hs
libraries/base/GHC/IO/Handle/Text.hs
libraries/base/GHC/IO/Handle/Types.hs
libraries/base/GHC/List.hs
libraries/base/GHC/Natural.hs
libraries/base/GHC/Pack.hs
libraries/base/GHC/RTS/Flags.hsc
libraries/base/GHC/Real.hs
libraries/base/GHC/Show.hs
libraries/base/GHC/Stack.hs
libraries/base/GHC/Stack/Types.hs
libraries/base/Numeric.hs
libraries/base/Prelude.hs
libraries/base/System/Environment/ExecutablePath.hsc
libraries/base/System/IO.hs
libraries/base/Text/ParserCombinators/ReadP.hs
libraries/base/Text/Printf.hs
libraries/base/Text/Read.hs
libraries/base/Text/Read/Lex.hs
libraries/base/changelog.md
libraries/base/codepages/MakeTable.hs
libraries/base/tests/readFloat.stderr
libraries/stm
testsuite/.gitignore
testsuite/tests/array/should_run/arr003.stderr
testsuite/tests/array/should_run/arr004.stderr
testsuite/tests/array/should_run/arr007.stderr
testsuite/tests/array/should_run/arr008.stderr
testsuite/tests/ffi/should_run/fptrfail01.stderr
testsuite/tests/ghci.debugger/scripts/break009.stdout
testsuite/tests/ghci/scripts/T10501.stderr
testsuite/tests/simplCore/should_compile/EvalTest.stdout
testsuite/tests/th/TH_exn2.stderr
testsuite/tests/typecheck/should_run/T11049.hs [new file with mode: 0644]
testsuite/tests/typecheck/should_run/T11049.stderr [new file with mode: 0644]
testsuite/tests/typecheck/should_run/T11049.stdout [new file with mode: 0644]
testsuite/tests/typecheck/should_run/all.T