Typed throws

It's a nice, simple formalization of some of the type-system behavior, but it doesn't actually change the key question with rethrows, which is whether the signature of A below is equivalent to that of B or that of C:

// A
func foo(fn: () throws -> Void) rethrows

// B
func foo<erased E: Error>(fn: () throws E -> Void) rethrows E

// C
func foo<erased E: Error>(fn: () throws E -> Void) rethrows Error

B is the more aggressive answer, and it would generally allow callers of higher-order operations like && to maintain more precise error types. However, C is the current rule. If you assume rule B when calling a rethrows function written as A and compiled under rule C, the type system will be unsound, and if you enforce rule B instead of rule C when compiling a rethrows function written as A, you may reject code that was previously accepted.

You may also have noticed the erased that I added in the signatures above. Without it, neither of these interpretations is actually ABI-compatible with the current interpretation of A, because A does not actually take a concrete type argument E.

7 Likes