It’s great to see progress on typed throws! I have a few design points to consider that are not mentioned in the posts you linked.
Non-throwing error types
Both the proposal draft and the post from @John_McCall post seem to assume all non-throwing functions have error type of Never
. This would be unfortunate. All functions with uninhabited error types should be considered non-throwing. This implies a tweak to John’s expression for computing a rethrown error type:
func foo<AError: Error, BError: Error>(a: () throws(AError) -> Int,
b: () throws(BError) -> Int)
throws(errorUnion(AError, BError) == Never ? Never : Error) -> Int
Becomes
func foo<AError: Error, BError: Error>(a: () throws(AError) -> Int,
b: () throws(BError) -> Int)
throws(errorUnion(AError, BError) == Never || AError is uninhabitable && BError is uninhabitable ? Never : Error) -> Int
This expression still leaves something to be desired: AError
and BError may have a more specific common supertype than
Error`. Ideally the compiler would be able to figure this out.
Typed rethrows
The fundamental semantic of rethrows
is that a function can only throw when an argument actually throws. In the presence of typed errors, it should be possible to catch and transform errors before rethrowing. This implies it should be possible to write rethrows TransformedError
regardless of the error types thrown by arguments. In such a function, the body would catch the errors thrown by its arguments and convert them to TransformedError
.
The difference between throws SomeError
and rethrows SomeError
would be subtle but important. When writing rethrows SomeError
it is only possible to throw if an argument first throws. The rethrows expression logic above would be modified slightly with the explicitly specified error type replacing Error
(or the computed common supertype). Thus, rethrows SomeError
may also be non-throwing depending on the arguments it receives.
Catch type inference
The proposal mentions that type inference for general catch clauses was omitted due to requiring breaking changes. Hopefully this could be included in Swift 6.
Opaque error types
It would be great if error types could be opaque just like return types. I didn’t see any mention of these in the proposal or John’s post and it seems like this feature interaction deserves consideration.