Note [Exceptions: asynchronous, synchronous, and unchecked]

GHC/Builtin/PrimOps.hs:320 compiler

There are three very different sorts of things in GHC-Haskell that are
sometimes called exceptions:

* Haskell exceptions:

  These are ordinary exceptions that users can raise with the likes
  of 'throw' and handle with the likes of 'catch'.  They come in two
  very different flavors:

  * Asynchronous exceptions:
    * These can arise at nearly any time, and may have nothing to do
      with the code being executed.
    * The compiler itself mostly doesn't need to care about them.
    * Examples: a signal from another process, running out of heap or stack
    * Even pure code can receive asynchronous exceptions; in this
      case, executing the same code again may lead to different
      results, because the exception may not happen next time.
    * See rts/RaiseAsync.c for the gory details of how they work.

  * Synchronous exceptions:
    * These are produced by the code being executed, most commonly via
      a call to the `raise#` or `raiseIO#` primops.
    * At run-time, if a piece of pure code raises a synchronous
      exception, it will always raise the same synchronous exception
      if it is run again (and not interrupted by an asynchronous
      exception).
    * In particular, if an updatable thunk does some work and then
      raises a synchronous exception, it is safe to overwrite it with
      a thunk that /immediately/ raises the same exception.
    * Although we are careful not to discard synchronous exceptions, we
      are very liberal about re-ordering them with respect to most other
      operations.  See the paper "A semantics for imprecise exceptions"
      as well as Note [Precise exceptions and strictness analysis] in
      GHC.Types.Demand.

* Unchecked exceptions:

  * These are nasty failures like seg-faults or primitive Int# division
    by zero.  They differ from Haskell exceptions in that they are
    un-recoverable and typically bring execution to an immediate halt.
  * We generally treat unchecked exceptions as undefined behavior, on
    the assumption that the programmer never intends to crash the
    program in this way.  Thus we have no qualms about replacing a
    division-by-zero with a recoverable Haskell exception or
    discarding an indexArray# operation whose result is unused.

References 1

Referenced by 2