If a method is declared with the rethrows
keyword then all the closures that throw are considered. There is no way to select only a subset of the throwing arguments.
This proposal extends the rethrows
syntax to allow to select which of the throwing arguments should be consider by the rethrows
.
The new syntax will include after the rethrows
comma separated indexes of the position of the throwing arguments that should be consider for the rethrows
. For example:
// The method will throw only if the first closure argument throws
func method(_ aClosure: () throws -> (), aOtherClosure: () throws -> ()) rethrows(0)
// The method will throw if the first or second closure argument throws
func method(_ aClosure: () throws -> (), aOtherClosure: () throws -> ()) rethrows(0, 1)
//The above is equivalent with the default behaviour
func method(_ aClosure: () throws -> (), aOtherClosure: () throws -> ()) rethrows
An example of a practical usecase
I want to improve the XCTAssertThrowsError so that when the error handler throws then the XCTAssertThrowsError also throws.
But If I declare the XCTAssertThrowsError with rethrows then it will also throw if the expression closure throws
(that is something we do not want since this is error should be handled internally).
With this improvement we should be able to write:
public func XCTAssertThrowsError<T>(_ expression: @autoclosure () throws -> T,
_ message: @autoclosure () -> String = "",
file: StaticString = #file,
line: UInt = #line,
_ errorHandler: (_ error: Swift.Error) throws -> Void = { _ in }) rethrows(0)
Current workaround
One workaround you can currently use the have the same effect is to create a second method that rethrows and overloads the first method by declaring the arguments you want to be consider for the rethrow to throw.
For example:
func foo(f: () throws -> () = {}, g: () -> () = {}) {
}
func foo(f: () throws -> () = {}, g: () throws -> () = {}) rethrows {
}
//The above two method will have the same effect as:
func foo(f: () throws -> () = {}, g: () throws -> () = {}) rethrows(1) {
}