Note [Exceptions: asynchronous, synchronous, and unchecked]
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
- Precise exceptions and strictness analysis GHC.Types.Demand
Referenced by 2
- Classifying primop effects GHC.Builtin.PrimOps ×2