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.