Using typed-throws (SE-0413) in Swift 6.0 (Xcode 16.0), it can correctly detect typed errors. Consider:
enum MyError: Error {
case one
case two
}
func funcWithTypedThrow() async throws(MyError) {…}
If you use separate catch
statements for those individual MyError
cases, the compiler will incorrectly conclude that the catches are not exhaustive:
// An example where typed-throw correctly infers the type of the thrown error, but
// incorrectly concludes catch is not exhaustive.
func foo() async {
do {
try await funcWithTypedThrow() // Swift 6.0 compiler incorrectly produces error: “Errors thrown from here are not handled because the enclosing catch is not exhaustive”
} catch .one {
print("one")
} catch .two {
print("two")
}
}
But if I add an extra catch
to silence that error, the compiler will realize that this is unnecessary and will warn that it “will never be executed”:
// In this example, I added extra `catch` to silence the above error, but now
// the compiler now warns us that that this extra `catch` is unnecessary.
func bar() async {
do {
try await funcWithTypedThrow()
} catch .one {
print("one")
} catch .two {
print("two")
} catch { // Swift 6.0 compiler correctly produces warning: “Case will never be executed”
print("this is required to silence 'non-exhaustive' error, but generates a 'will never be executed' warning")
}
}
How can I get around this issue?
One can just catch the typed-error and then use a switch
statement:
func qux() async {
do {
try await funcWithTypedThrow()
} catch {
switch error {
case .one: print("one")
case .two: print("two")
}
}
}
This seems to avoid the incorrect “exhaustiveness” checks when using separate catch
clauses.