Catching errors of different types

Today I've noticed the typed errors proposal on GitHub.
I'm really happy to see it happening as it's something that I wanted to have in the language for aeons. A big thank you to all those who contributed.

I just want to raise one point. When a do statement can throw errors with different concrete types, receiving an any Error in the catch block is a huge lost opportunity in my opinion.

do {
  try callCat()
  try callKids()
} catch {
  // error has type 'any Error', as it does today
}

I know good practices imply wrapping errors in your own types, and perhaps Swift wants to encourage this, however, in practice, it requires the kind of discipline few teams have. Keeping the information about the possible types, would be a huge advantage. It would address one of the most annoying problem when working 3rd party code that throws, cut a lot of boilerplate in upstream do-catch blocks, and make the entire mechanism fully type safe.

There are a few ways to implement this I think, some of them backwards compatible, it could be by passing an errorContext as well to the catch block, or even have a special object OneOf<KidError, CatError> that can be conditionally cast as either KidError or CatError but casting to anything else would rise a compile time error (this would be neat, but I imagine OneOf in itself would need to be a proposal). There are probably other ways, I haven't fully give it a thought, but I know that adding this into the language would a life-changer for many.

The proposal considered it, but rejected it:

Rationale: While it would be possible to compute a more precise "union" type of different error types, doing so is potentially an expensive operation at compile time and run time, as well as being harder for the programmer to reason about. If in the future it becomes important to tighten up the error types, that could be done in a mostly source-compatible manner.

2 Likes

Phu, that's a bummer, but at least there's some hope for the future!

A more likely possibility is exhaustiveness checking with multiple catch let error as SomeError statements, which is almost as good. And you can always provide the union yourself if it's that important.

4 Likes