Skip to content

Instantly share code, notes, and snippets.

@robertmryan
Created September 26, 2024 18:25
Show Gist options
  • Save robertmryan/feaa23876da000e681d41b81031fb33b to your computer and use it in GitHub Desktop.
Save robertmryan/feaa23876da000e681d41b81031fb33b to your computer and use it in GitHub Desktop.
enum MyError: Error {
case one
case two
}
actor Example {
func funcWithTypedThrow() async throws(MyError) { throw .one }
// OK
func foo() async {
// closures can be defined as throwing a particular error type
let closure: () async throws(MyError) -> Void = { try await self.funcWithTypedThrow() }
// thus, this is OK
do {
try await closure()
} catch {
switch error {
case .one: print("one")
case .two: print("two")
}
}
}
// Not OK
func bar() async {
// but closures do not (yet) infer the typed-throw type
let closure = { try await self.funcWithTypedThrow() }
// thus, this will produce the following compile-time errors
do {
try await closure()
} catch {
switch error {
case .one: print("one") // Error: Type '_ErrorCodeProtocol' has no member 'one'
case .two: print("two") // Error: Type '_ErrorCodeProtocol' has no member 'two'
}
}
}
}
@robertmryan
Copy link
Author

What I find interesting is that in the closure example, it clearly has determined that the error is a MyError (as evidenced by “Quick help”), but the switch statement somehow does not!

typed-throw closure

@robertmryan
Copy link
Author

I suspect this is all related to #74555.

Also, FWIW, SE-0413 seems to suggest that typed throw type inference is a work-in-progress:

Note: the originally accepted version of this proposal included type inference changes intended for Swift 6.0 that were behind the upcoming feature flag FullTypedThrows. These type inference changes did not get implemented in Swift 6.0, and have therefore been removed from this proposal and placed into “Future Directions” so they can be revisited once implemented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment