// [0] do throwable tests, then non-throwable mutation
// (The tests are from a predicate that's a parameter for this function.)
do {
// [1] do throwable tests, then non-throwable mutation
do {
// [2] do throwable tests, then non-throwable mutation
} catch {
// [-1] undo the mutable part of [1]
throw error
}
} catch {
// [-0] undo the mutable part of [0]
throw error // "A function declared 'rethrows' may only throw if its parameter does"
}
Why can't nested throwing cascade? Or am I doing something wrong?
Edit: I tried "catch let someIdentfier," with different names for each level. Didn't work.
This shows the error the OP is seeing, and I think makes it clear why that error occurs (the compiler can't trace that the exception caught in the outer block can only come from the throw in the inner block, which can only be a rethrow).
func doStuff(
with closure: () throws -> Void
) rethrows -> Void {
do {
do {
try closure()
} catch {
throw error
}
} catch {
throw error // "A function declared 'rethrows' may only throw if its parameter does"
}
}
Typed throws should solve the issue, but does not:
func doStuff<E: Error>(
with closure: () throws(E) -> Void
) throws(E) -> Void {
do {
do {
try closure()
} catch {
throw error
}
} catch {
throw error // error: thrown expression type 'any Error' cannot be converted to error type 'E'
}
}