Skip to content
  • Eric Seidel's avatar
    Allow CallStacks to be frozen · 380b25ea
    Eric Seidel authored
    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
    380b25ea