Overall, this looks fantastic and I'm very glad that this finally has the chance to become a part of the language.
I have one minor complaint though:
do {
try callCat() // throws CatError
try callKids() // throw KidError
} catch {
// implicit 'error' variable has type 'any Error'
}
In essence, when there are multiple possible thrown error types, we immediately resolve to the untyped equivalent of any Error . We will refer to this notion as a type function errorUnion(E1, E2, ..., EN) , which takes N different error types (e.g., for throwing sites within a do block) and produces the union error type of those types. Our definition and use of errorUnion for typed throws subsumes the existing rule for untyped throws, in which every throw site produces an error of type any Error .
While I'm totally fine with the rule that multiple differently typed errors in a do block just produce an any Error in an unconstrained catch, I wonder why it isn't possible to exhaustively catch the errors like so:
do {
try callCat() // throws CatError
try callKids() // throws KidError
} catch is CatError {
print("Error was CatError")
} catch is KidError {
print("Error was KidError")
} // no catch-all needed because catch clauses are exhaustive
The proposal has the following note about this:
Note : Exhaustiveness checking in the general is expensive at compile time, and the existing language uses the presence of an unconditional catch block as the indicator for an exhaustive do...catch . See the section on closure thrown type inference for more details about inferring throwing closures.
Can someone explain what's so expensive about exhaustiveness checking? In principle we would just have to loop over every error thrown in the do block and look if it is convertible to one of the catch clauses, no? I cannot imagine why this should be any harder than exhaustiveness checking for switch statements/expressions.
If there is a way to make catch clauses exhaustive without having to have a catch-all clause that would be fantastic.
Definitely. The lack of typed throws was always one of the major pain points for me when using Swift.
IMHO, yes. The syntax feels intuitive, it will bring throws back to feature parity with Result/Task and will hopefully improve the standard library and especially the concurrency API in the long run.
I have used checked exceptions in Java before, but it feels like these are playing in a different league. I think, it's positive that the default in Swift will still be untyped errors, unlike Java where you either have exceptions that you don't have to declare at all, or the checked ones which have to be typed for every function that uses them. Swift seems to be striking a good balance there.
Honestly, the typed throws system in Swift feels very much like nice sugar around the error handling system in Rust, which I already really like.
I read and participated in basically all discussion and pitch threads regarding this topic, carefully read this proposal as well as some of its earlier revisions, and even started to work with some others on an implementation for this feature a while ago (even though we didn't really get far due to lack of compiler knowledge and time).