What Are the Differences Between Throws and Rethrows in Swift

What are the differences between throws and rethrows in Swift?

From "Declarations" in the Swift book:

Rethrowing Functions and Methods

A function or method can be declared with the rethrows keyword to
indicate that it throws an error only if one of it’s function
parameters throws an error. These functions and methods are known as
rethrowing functions and rethrowing methods. Rethrowing functions and
methods must have at least one throwing function parameter.

A typical example is the map method:

public func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]

If map is called with a non-throwing transform, it does not throw
an error itself and can be called without try:

// Example 1:

let a = [1, 2, 3]

func f1(n: Int) -> Int {
return n * n
}

let a1 = a.map(f1)

But if map is called with a throwing closure then itself can throw
and must be called with try:

// Example 2:

let a = [1, 2, 3]
enum CustomError: Error {
case illegalArgument
}

func f2(n: Int) throws -> Int {
guard n >= 0 else {
throw CustomError.illegalArgument
}
return n*n
}


do {
let a2 = try a.map(f2)
} catch {
// ...
}
  • If map were declared as throws instead of rethrows then you would
    have to call it with try even in example 1,
    which is "inconvenient" and bloats the code unnecessary.
  • If map were declared without throws/rethrows then you could not
    call it with a throwing closure as in example 2.

The same is true for other methods from the Swift Standard Library
which take function parameters: filter(), index(where:), forEach() and many many more.

In your case,

func throwCustomError(function:(String) throws -> ()) throws

denotes a function which can throw an error, even if called with
a non-throwing argument, whereas

func rethrowCustomError(function:(String) throws -> ()) rethrows

denotes a function which throws an error only if called with a
throwing argument.

Roughly speaking, rethrows is for functions which do not throw
errors "on their own", but only "forward" errors from their function
parameters.

How to declare a rethrowing function?

Remember, the argument is of type () -> Int! So you need to call the function passed in to get the result! You also need try since the function can throw.

func handleResult(_ index: (() throws ->  Int)) rethrows {
print(try index() * 2) // see the "()"?
}

Now you can use it like this:

let myArray = [true]
try handleResult(myArray.indexOfFirstTrue)

rethrows for class/struct instance method in swift error handling

As said here: https://stackoverflow.com/a/33350601/1370336, in your "MiddleParser" struct, you don't have to wrap the call in a do - catch block (since your function is marked with throws), just use:

inners.append(try self.innerParser.parse(innerJson))

Throw from a trailing closure in Swift

func innerClosure(a: String, completion: (String) throws ->Void) {
try? completion(a + ", World")
}

does not throw an error because try? is an “optional try”: It returns an Optional which is nil in the case of an error. Here the return value is ignored, so that errors are ignored silently.

What you want is

func innerClosure(a: String, completion: (String) throws ->Void) rethrows {
try completion(a + ", World")
}

which makes innerClosure() a throwing function only if called with a throwing parameter.

func iCanThrow() can also be marked as rethrows instead of throws because it does not throw an error “on its own.”
See also What are the differences between throws and rethrows in Swift?.

Save rethrowing function as a non-throwing closure

Until someone comes up with a better solution: Use a wrapper

func f(_ c: () throws -> Void) rethrows { try c() }

let x: (() -> Void) -> Void = { f($0) }

Generic requirement that Some: AsyncSequence is not throwing

When this proposal is fully implemented you will be able to express conformance to a failable sequence by providing some syntax sugar

extension AsyncSequence where nothrow AsyncIterator {

or

struct Foo<S: nothrow AsyncSequence>

This comes from the @rethrows annotation currently attached to AsyncSequence

@rethrows public protocol AsyncSequence

swift syntax. What is R in withUnsafeMutableBytes R (_...

withUnsafeMutableBytes<R>(_: (UnsafeMutableRawBufferPointer) throws -> R) rethrows -> R means that:

  • Function withUnsafeMutableBytes takes a function/closure (that may throw error) from UnsafeMutableRawBufferPointer to some generic type R. What R depends on the caller.
  • Function withUnsafeMutableBytes returns value of the same generic type R taken function returns. And it may rethrow error, if it was thrown by the closure.

So basically generic parameter R here is just a way to say that return types of withUnsafeMutableBytes and the closure it takes will be identical, and it's not hardcoded.



Related Topics



Leave a reply



Submit