So, we probably want to maintain src compat:
do {
try throwUntypedError()
throw FooError.error
} catch {
// error is Error
}
and the pitch wants to add handling on typed throws
// ok, exhaustive check
do {
try throwFooError()
} catch let error as FooError {
}
There're a few cases I'd like to clarify. Do any of the below compile, and if so, what would their behaviours be?
When functions throw different types and we catch
both of them:
// Is this exhaustive?
do {
try throwFooError()
try throwBarError()
} catch let error as FooError {
} catch let error as BarError {
}
What if we don't annotate the catch
block:
do {
try throwFooError()
try throwBarError()
} catch {
// What is `error` type?
}
When function mix throwing functions, and throw
syntax, especially when the thrown errors are the same type
// Is this exhaustive?
do {
try throwFooError()
throw FooError.error
} catch let error as FooError {
}
and the with unannotated handling:
do {
try throwFooError()
throw FooError.error
} catch {
// What is error type
}
This is discussed above: when there are only throw
statements:
do {
throw FooError.error
throw BarError.error
} catch let error as FooError {
} catch let error as BarError {
}
It is unintuitive to have throw
syntax be untyped by default. We still need typed throw
s when throwing from inside the function with typed error. Now we'd have both typed and untyped throw
s with virtually no way to distinguish between the two.
What if instead have all throw
statements be typed, but don't explicitly infer it in the catch block. In which case, we only use typed error for exhaustivity checking.
do {
throw FooError.error
} catch {
// error is `Error`
}
// OK - is exhausitive
do {
throw FooError.error
} catch let error as FooError {
// error is `FooError`
}