Error Handling in Swift 2.0
===========================

As a tentpole feature for Swift 2.0, we are introducing a new
first-class error handling model.  This feature provides standardized
syntax and language affordances for throwing, propagating, catching,
and manipulating recoverable error conditions.

Error handling is a well-trod path, with many different approaches in
other languages, many of them problematic in various ways.  We believe
that our approach provides an elegant solution, drawing on the lessons
we've learned from other languages and fixing or avoiding some of the
pitfalls.  The result is expressive and concise while still feeling
explicit, safe, and familiar; and we believe it will work beautifully
with the Cocoa APIs.

We're intentionally not using the term "exception handling", which
carries a lot of connotations from its use in other languages.  Our
proposal has some similarities to the exceptions systems in those
languages, but it also has a lot of important differences.

Kinds of Error
--------------

What exactly is an "error"?  There are many possible error conditions,
and they don't all make sense to handle in exactly the same way,
because they arise in different circumstances and programmers have to
react to them differently.

We can break errors down into four categories, in increasing order of
severity:

A **simple domain error** arises from an operation that can fail in
some obvious way and which is often invoked speculatively.  Parsing an
integer from a string is a really good example.  The client doesn't
need a detailed description of the error and will usually want to
handle the error immediately.  These errors are already well-modeled
by returning an optional value; we don't need a more complex language
solution for them.

A **recoverable error** arises from an operation which can fail in
complex ways, but whose errors can be reasonably anticipated in
advance.  Examples including opening a file or reading from a network
connection.  These are the kinds of errors that Apple's APIs use
NSError for today, but there are close analogues in many other APIs,
such as ``errno`` in POSIX.

Ignoring this kind of error is usually a bad idea, and it can even be
dangerous (e.g. by introducing a security hole).  Developers should be
strongly encouraged to write code that handles the error.  It's common
for developers to want to handle errors from different operations in
the same basic way, either by reporting the error to the user or
passing the error back to their own clients.

These errors will be the focus on this proposal.

The final two classes of error are outside the scope of this proposal.
A **universal error** is theoretically recoverable, but by its nature
the language can't help the programmer anticipate where it will come
from.  A **logic failure** arises from a programmer mistake and should
not be recoverable at all.  In our system, these kinds of errors are
reported either with Objective-C/C++ exceptions or simply by
logging a message and calling ``abort()``.  Both kinds of error are
discussed extensively in the rationale.  Having considered them
carefully, we believe that we can address them in a later release
without significant harm.

Aspects of the Design
---------------------

This approach proposed here is very similar to the error handling
model manually implemented in Objective-C with the ``NSError``
convention.  Notably, the approach preserves these advantages of this
convention:

- Whether a method produces an error (or not) is an explicit part of
  its API contract.

- Methods default to *not* producing errors unless they are explicitly
  marked.
  
- The control flow within a function is still mostly explicit: a
  maintainer can tell exactly which statements can produce an error,
  and a simple inspection reveals how the function reacts to the
  error.
  
- Throwing an error provides similar performance to allocating an
  error and returning it -- it isn't an expensive, table-based stack
  unwinding process.
  
- Cocoa APIs using standard ``NSError`` patterns can be imported into
  this world automatically.  Other common patterns (e.g. ``CFError``,
  ``errno``) can be added to the model in future versions of Swift.

In addition, we feel that this design improves on Objective-C's error
handling approach in a number of ways:

- It eliminates a lot of boilerplate control-flow code for propagating
  errors.

- The syntax for error handling will feel familiar to people used to
  exception handling in other languages.

- Defining custom error types is simple and ties in elegantly with
  Swift enums.

As to basic syntax, we decided to stick with the familiar language of
exception handling.  We considered intentionally using different terms
(like ``raise`` / ``handle``) to try to distinguish our approach from
other languages.  However, by and large, error propagation in this
proposal works like it does in exception handling, and people are
inevitably going to make the connection.  Given that, we couldn't find
a compelling reason to deviate from the ``throw`` / ``catch`` legacy.

This document just contains the basic proposal and will be very
light on rationale.  We considered many different languages and
programming environments as part of making this proposal, and there's
an extensive discussion of them in the separate rationale document.
For example, that document explains why we don't simply allow all
functions to throw, why we don't propagate errors using simply an
``ErrorOr<T>`` return type, and why we don't just make error propagation
part of a general monad feature.  We encourage you to read that
rationale if you're interested in understanding why we made the
decisions we did.

With that out of the way, let's get to the details of the proposal.

Typed propagation
-----------------

Whether a function can throw is part of its type.  This applies to all
functions, whether they're global functions, methods, or closures.

By default, a function cannot throw.  The compiler statically enforces
this: anything the function does which can throw must appear in a
context which handles all errors.

A function can be declared to throw by writing ``throws`` on the
function declaration or type::

  func foo() -> Int {  // This function is not permitted to throw.
  func bar() throws -> Int {   // This function is permitted to throw.

``throws`` is written before the arrow to give a sensible and consistent
grammar for function types and implicit ``()`` result types, e.g.::

  func baz() throws {

  // Takes a 'callback' function that can throw.
  // 'fred' itself can also throw.
  func fred(callback: (UInt8) throws -> ()) throws {

  // These are distinct types.
  let a : () -> () -> ()
  let b : () throws -> () -> ()
  let c : () -> () throws -> ()
  let d : () throws -> () throws -> ()

For curried functions, ``throws`` only applies to the innermost
function.  This function has type ``(Int) -> (Int) throws -> Int``::

  func jerry(i: Int)(j: Int) throws -> Int {

``throws`` is tracked as part of the type system: a function value
must also declare whether it can throw.  Functions that cannot throw
are a subtype of functions that can, so you can use a function that
can't throw anywhere you could use a function that can::

  func rachel() -> Int { return 12 }
  func donna(generator: () throws -> Int) -> Int { ... }

  donna(rachel)

The reverse is not true, since the caller would not be prepared to
handle the error.

A call to a function which can throw within a context that is not
allowed to throw is rejected by the compiler.

It isn't possible to overload functions solely based on whether the
functions throw.  That is, this is not legal::

  func foo() { 
  func foo() throws {

A throwing method cannot override a non-throwing method or satisfy a
non-throwing protocol requirement.  However, a non-throwing method can
override a throwing method or satisfy a throwing protocol requirement.

It is valuable to be able to overload higher-order functions based on
whether an argument function throws, so this is allowed::

  func foo(callback: () throws -> Bool) {
  func foo(callback: () -> Bool) {

``rethrows``
~~~~~~~~~~~~

Functions which take a throwing function argument (including as an
autoclosure) can be marked as ``rethrows``::

  extension Array {
    func map<U>(fn: ElementType throws -> U) rethrows -> [U]
  }

It is an error if a function declared ``rethrows`` does not include a
throwing function in at least one of its parameter clauses.

``rethrows`` is identical to ``throws``, except that the function
promises to only throw if one of its argument functions throws.

More formally, a function is *rethrowing-only* for a function *f* if:

- it is a throwing function parameter of *f*,

- it is a non-throwing function, or

- it is implemented within *f* (i.e. it is either *f* or a function or
  closure defined therein) and it does not throw except by either:

  - calling a function that is rethrowing-only for *f* or

  - calling a function that is ``rethrows``, passing only functions
    that are rethrowing-only for *f*.

It is an error if a ``rethrows`` function is not rethrowing-only for
itself.

A ``rethrows`` function is considered to be a throwing function.
However, a direct call to a ``rethrows`` function is considered to not
throw if it is fully applied and none of the function arguments can
throw.  For example::

  // This call to map is considered not to throw because its
  // argument function does not throw.
  let absolutePaths = paths.map { "/" + $0 }

  // This call to map is considered to throw because its
  // argument function does throw.
  let streams = try absolutePaths.map { try InputStream(filename: $0) }

For now, ``rethrows`` is a property of declared functions, not of
function values.  Binding a variable (even a constant) to a function
loses the information that the function was ``rethrows``, and calls to
it will use the normal rules, meaning that they will be considered to
throw regardless of whether a non-throwing function is passed.

For the purposes of override and conformance checking, ``rethrows``
lies between ``throws`` and non-``throws``.  That is, an ordinary
throwing method cannot override a ``rethrows`` method, which cannot
override a non-throwing method; but an ordinary throwing method can be
overridden by a ``rethrows`` method, which can be overridden by a
non-throwing method.  Equivalent rules apply for protocol conformance.

Throwing an error
-----------------

The ``throw`` statement begins the propagation of an error.  It always
take an argument, which can be any value that conforms to the
``ErrorType`` protocol (described below).

::

  if timeElapsed > timeThreshold {
    throw HomeworkError.Overworked
  }

  throw NSError(domain: "whatever", code: 42, userInfo: nil)

As mentioned above, attempting to throw an error out of a function not
marked ``throws`` is a static compiler error.

Catching errors
---------------

A ``catch`` clause includes an optional pattern that matches the
error.  This pattern can use any of the standard pattern-matching
tools provided by ``switch`` statements in Swift, including boolean
``where`` conditions.  The pattern can be omitted; if so, a ``where``
condition is still permitted.  If the pattern is omitted, or if it
does not bind a different name to the error, the name ``error`` is
automatically bound to the error as if with a ``let`` pattern.

The ``try`` keyword is used for other purposes which it seems to fit far
better (see below), so ``catch`` clauses are instead attached to a
generalized ``do`` statement::

  // Simple do statement (without a trailing while condition),
  // just provides a scope for variables defined inside of it.
  do {
     let x = foo()
  }

  // do statement with two catch clauses.
  do {
    ...

  } catch HomeworkError.Overworked {
    // a conditionally-executed catch clause

  } catch _ {
    // a catch-all clause.  
  }

As with ``switch`` statements, Swift makes an effort to understand
whether catch clauses are exhaustive.  If it can determine it is, then
the compiler considers the error to be handled.  If not, the error
automatically propagates out out of scope, either to a lexically
enclosing ``catch`` clause or out of the containing function (which must
be marked ``throws``).

We expect to refine the ``catch`` syntax with usage experience.

``ErrorType``
-------------

The Swift standard library will provide ``ErrorType``, a protocol with
a very small interface (which is not described in this proposal).  The
standard pattern should be to define the conformance of an ``enum`` to
the type::

  enum HomeworkError : ErrorType {
    case Overworked
    case Impossible
    case EatenByCat(Cat)
    case StopStressingMeWithYourRules
  }

The ``enum`` provides a namespace of errors, a list of possible errors
within that namespace, and optional values to attach to each option.

Note that this corresponds very cleanly to the ``NSError`` model of an
error domain, an error code, and optional user data.  We expect to
import system error domains as enums that follow this approach and
implement ``ErrorType``.  ``NSError`` and ``CFError`` themselves will also
conform to ``ErrorType``.

The physical representation (still being nailed down) will make it
efficient to embed an ``NSError`` as an ``ErrorType`` and vice-versa.  It
should be possible to turn an arbitrary Swift ``enum`` that conforms to
``ErrorType`` into an ``NSError`` by using the qualified type name as the
domain key, the enumerator as the error code, and turning the payload
into user data.

Automatic, marked, propagation of errors
----------------------------------------

Once an error is thrown, Swift will automatically propagate it out of
scopes (that permit it), rather than relying on the programmer to
manually check for errors and do their own control flow.  This is just
a lot less boilerplate for common error handling tasks.  However,
doing this naively would introduce a lot of implicit control flow,
which makes it difficult to reason about the function's behavior.
This is a serious maintenance problem and has traditionally been a
considerable source of bugs in languages that heavily use exceptions.

Therefore, while Swift automatically propagates errors, it requires
that statements and expressions that can implicitly throw be marked
with the ``try`` keyword.  For example::

  func readStuff() throws {
    // loadFile can throw an error.  If so, it propagates out of readStuff.
    try loadFile("mystuff.txt")

    // This is a semantic error; the 'try' keyword is required
    // to indicate that it can throw.
    var y = stream.readFloat()

    // This is okay; the try covers the entire statement.
    try y += stream.readFloat()

    // This try applies to readBool().
    if try stream.readBool() {
      // This try applies to both of these calls.
      let x = try stream.readInt() + stream.readInt()
    }

    if let err = stream.getOutOfBandError() {
      // Of course, the programmer doesn't have to mark explicit throws.
      throw err
    }
  }

Developers can choose to "scope" the ``try`` very tightly by writing it
within parentheses or on a specific argument or list element::

  // Ok.
  let x = (try stream.readInt()) + (try stream.readInt())

  // Semantic error: the try only covers the parenthesized expression.
  let x2 = (try stream.readInt()) + stream.readInt()

  // The try applies to the first array element.  Of course, the
  // developer could cover the entire array by writing the try outside.
  let array = [ try foo(), bar(), baz() ]

Some developers may wish to do this to make the specific throwing
calls very clear.  Other developers may be content with knowing that
something within a statement can throw. The compiler's fixit hints will
guide developers towards inserting a single ``try`` that covers the entire
statement.  This could potentially be controlled someday by a coding
style flag passed to the compiler.

``try!``
~~~~~~~~

To concisely indicate that a call is known to not actually throw at
runtime, ``try`` can be decorated with ``!``, turning the error check
into a runtime assertion that the call does not throw.

For the purposes of checking that all errors are handled, a ``try!``
expression is considered to handle any error originating from within
its operand.

``try!`` is otherwise exactly like ``try``: it can appear in exactly
the same positions and doesn't affect the type of an expression.

Manual propagation and manipulation of errors
---------------------------------------------

Taking control over the propagation of errors is important for some
advanced use cases (e.g. transporting an error result across threads
when synchronizing a future) and can be more convenient or natural for
specific use cases (e.g. handling a specific call differently within a
context that otherwise allows propagation).

As such, the Swift standard library should provide a standard
Rust-like ``Result<T>`` enum, along with API for working with it,
e.g.:

- A function to evaluate an error-producing closure and capture the
  result as a ``Result<T>``.

- A function to unpack a ``Result<T>`` by either returning its
  value or propagating the error in the current context.

This is something that composes on top of the basic model, but that
has not been designed yet and details aren't included in this
proposal.

The name ``Result<T>`` is a stand-in and needs to be designed and
reviewed, as well as the basic operations on the type.

``defer``
---------

Swift should provide a ``defer`` statement that sets up an *ad hoc*
clean-up action to be run when the current scope is exited.  This
replicates the functionality of a Java-style ``finally``, but more
cleanly and with less nesting.

This is an important tool for ensuring that explicitly-managed
resources are released on all paths.  Examples include closing a
network connection and freeing memory that was manually allocated.  It
is convenient for all kinds of error-handling, even manual propagation
and simple domain errors, but is especially nice with automatic
propagation.  It is also a crucial part of our long-term vision for
universal errors.

``defer`` may be followed by an arbitrary statement.  The compiler
should reject a ``defer`` action that might terminate early, whether by
throwing or with ``return``, ``break``, or ``continue``.

Example::

  if exists(filename) {
    let file = open(filename, O_READ)
    defer close(file)

    while let line = try file.readline() {
      ...
    }

    // close occurs here, at the end of the formal scope.
  }

If there are multiple defer statements in a scope, they are guaranteed
to be executed in reverse order of appearance.  That is::

  let file1 = open("hello.txt")
  defer close(file1)
  let file2 = open("world.txt")
  defer close(file2)
  ...
  // file2 will be closed first.

A potential extension is to provide a convenient way to mark that a
defer action should only be taken if an error is thrown.  This is a
convenient shorthand for controlling the action with a flag.  We will
evaluate whether adding complexity to handle this case is justified
based on real-world usage experience.

Importing Cocoa
---------------

If possible, Swift's error-handling model should transparently work
with the SDK with a minimal amount of effort from framework owners.

We believe that we can cover the vast majority of Objective-C APIs
with ``NSError**`` out-parameters by importing them as ``throws`` and
removing the error clause from their signature.  That is, a method
like this one from ``NSAttributedString``::

  - (NSData *)dataFromRange:(NSRange)range
         documentAttributes:(NSDictionary *)dict
                      error:(NSError **)error;

would be imported as::

  func dataFromRange(range: NSRange,
                     documentAttributes dict: NSDictionary) throws -> NSData

There are a number of cases to consider, but we expect that most can
be automatically imported without extra annotation in the SDK, by
using a couple of simple heuristics:

* The most common pattern is a ``BOOL`` result, where a false value
  means an error occurred.  This seems unambiguous.

* Also common is a pointer result, where a ``nil`` result usually
  means an error occurred.  This appears to be universal in
  Objective-C; APIs that can return ``nil`` results seem to do so via
  out-parameters.  So it seems to be safe to make a policy decision
  that it's okay to assume that a ``nil`` result is an error by
  default.

  If the pattern for a method is that a ``nil`` result means it produced
  an error, then the result can be imported as a non-optional type.

* A few APIs return ``void``.  As far as I can tell, for all of these,
  the caller is expected to check for a non-``nil`` error.

For other sentinel cases, we can consider adding a new clang attribute
to indicate to the compiler what the sentinel is:

* There are several APIs returning ``NSInteger`` or ``NSUInteger``.  At
  least some of these return 0 on error, but that doesn't seem like a
  reasonable general assumption.

* ``AVFoundation`` provides a couple methods returning
  ``AVKeyValueStatus``.  These produce an error if the API returned
  ``AVKeyValueStatusFailed``, which, interestingly enough, is not the
  zero value.

The clang attribute would specify how to test the return value for an
error.  For example::

  + (NSInteger)writePropertyList:(id)plist
                        toStream:(NSOutputStream *)stream
                          format:(NSPropertyListFormat)format
                         options:(NSPropertyListWriteOptions)opt
                           error:(out NSError **)error
    NS_ERROR_RESULT(0);

  - (AVKeyValueStatus)statusOfValueForKey:(NSString *)key
                                    error:(NSError **)
    NS_ERROR_RESULT(AVKeyValueStatusFailed);

We should also provide a Clang attribute which specifies that the
correct way to test for an error is to check the out-parameter.  Both
of these attributes could potentially be used by the static analyzer,
not just Swift.  (For example, they could try to detect an invalid
error check.)

Cases that do not match the automatically imported patterns and that
lack an attribute would be left unmodified (i.e., they'd keep their
NSErrorPointer argument) and considered "not awesome" in the SDK
auditing tool.  These will still be usable in Swift: callers will get
the NSError back like they do today, and have to throw the result
manually.

For initializers, importing an initializer as throwing takes
precedence over importing it as failable.  That is, an imported
initializer with a nullable result and an error parameter would be
imported as throwing.  Throwing initializers have very similar
constraints to failable initializers; in a way, it's just a new axis
of failability.

One limitation of this approach is that we need to be able to reconstruct
the selector to use when an overload of a method is introduced.  For this
reason, the import is likely to be limited to methods where  the error
parameter is the last one and the corresponding selector
chunk is either ``error:`` or the first chunk (see below).  Empirically,
this seems to do the right thing for all but two sets of APIs in the
public API:

* The ``ISyncSessionDriverDelegate`` category on ``NSObject`` declares
  half-a-dozen methods like this::

    - (BOOL)sessionDriver:(ISyncSessionDriver *)sender
            didRegisterClientAndReturnError:(NSError **)outError;

  Fortunately, these delegate methods were all deprecated in Lion, and
  are thus unavailable in Swift.

* ``NSFileCoordinator`` has half a dozen methods where the ``error:``
  clause is second-to-last, followed by a block argument.  These
  methods are not deprecated as far as I know.

The above translation rule would import methods like this one from
``NSDocument``::

  - (NSDocument *)duplicateAndReturnError:(NSError **)outError;

like so::

  func duplicateAndReturnError() throws -> NSDocument

The ``AndReturnError`` bit is common but far from universal; consider
this method from ``NSManagedObject``::

  - (BOOL)validateForDelete:(NSError **)error;

This would be imported as::

  func validateForDelete() throws

This is a really nice import, and it's somewhat unfortunate that we
can't import ``duplicateAndReturnError:`` as ``duplicate()``.


Potential future extensions to this model
-----------------------------------------

We believe that the proposal above is sufficient to provide a huge
step forward in error handling in Swift programs, but there is always
more to consider in the future.  Some specific things we've discussed
(and may come back to in the future) but don't consider to be core to
the Swift 2.0 model are:

Higher-order polymorphism
~~~~~~~~~~~~~~~~~~~~~~~~~

We should make it easy to write higher-order functions that behave
polymorphically with respect to whether their arguments throw.  This
can be done in a fairly simple way: a function can declare that it
throws if any of a set of named arguments do.  As an example (using
strawman syntax)::

  func map<T,U>(array: [T], fn: T -> U) throwsIf(fn) -> [U] {
    ...
  }

There's no need for a more complex logical operator than disjunction
for normal higher-order stuff.

This feature is highly desired (e.g. it would allow many otherwise
redundant overloads to be collapsed into a single definition), but it
may or may not make it into Swift 2.0 based on schedule limitations.

Generic polymorphism
~~~~~~~~~~~~~~~~~~~~

For similar reasons to higher-order polymorphism, we should consider
making it easier to parameterize protocols on whether their operations
can throw.  This would allow the writing of generic algorithms, e.g.
over ``Sequence``, that handle both conformances that cannot throw (like
``Array``) and those that can (like a hypothetical cloud-backed
implementation).

However, this would be a very complex feature, yet to be designed, and
it is far out-of-scope for Swift 2.0.  In the meantime, most standard
protocols will be written to not allow throwing conformances, so as to
not burden the use of common generic algorithms with spurious
error-handling code.

Statement-like functions
~~~~~~~~~~~~~~~~~~~~~~~~

Some functions are designed to take trailing closures that feel like
sub-statements.  For example, ``autoreleasepool`` can be used this way::

  autoreleasepool {
    foo()
  }

The error-handling model doesn't cause major problems for this.  The
compiler can infer that the closure throws, and ``autoreleasepool``
can be overloaded on whether its argument closure throws; the
overload that takes a throwing closures would itself throw.

There is one minor usability problem here, though.  If the closure
contains throwing expressions, those expression must be explicitly
marked within the closure with ``try``.  However, from the compiler's
perspective, the call to ``autoreleasepool`` is also a call that
can throw, and so it must also be marked with ``try``::

  try autoreleasepool {    // 'try' is required here...
    let string = try parseString() // ...and here.
    ...
  }

This marking feels redundant.  We want functions like
``autoreleasepool`` to feel like statements, but marks inside builtin
statements like ``if`` don't require the outer statement to be marked.
It would be better if the compiler didn't require the outer ``try``.

On the other hand, the "statement-like" story already has a number of
other holes: for example, ``break``, ``continue``, and ``return``
behave differently in the argument closure than in statements.  In the
future, we may consider fixing that; that fix will also need to
address the error-propagation problem.

``using``
~~~~~~~~~

A ``using`` statement would acquire a resource, holds it for a fixed
period of time, optionally binds it to a name, and then releases it
whenever the controlled statement exits.  ``using`` has many
similarities to ``defer``.  It does not subsume ``defer``, which is useful
for many ad-hoc and tokenless clean-ups.  But it could be convenient
for the common pattern of a type-directed clean-up.

Automatically importing CoreFoundation and C functions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

CF APIs use ``CFErrorRef`` pretty reliably, but there are several
problems here: 1) the memory management rules for CFErrors are unclear
and potentially inconsistent.  2) we need to know when an error is
raised.

In principle, we could import POSIX functions into Swift as throwing
functions, filling in the error from ``errno``.  It's nearly impossible
to imagine doing this with an automatic import rule, however; much
more likely, we'd need to wrap them all in an overlay.

In both cases, it is possible to pull these into the Swift error
handling model, but because this is likely to require massive SDK
annotations it is considered out of scope for iOS 9/OSX 10.11 & Swift 2.0.

Unexpected and universal errors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

As discussed above, we believe that we can extend our current model to
support untyped propagation for universal errors.  Doing this well,
and in particular doing it without completely sacrificing code size
and performance, will take a significant amount of planning and
insight.  For this reason, it is considered well out of scope for
Swift 2.0.

