[Question] Why does beginAsync
rethrow errors?
Although I posted about this topic before, let me post this again because I think it is important and I have received just few replies. Sorry if I missed some discussion about it.
In the proposal ( https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619 ), beginAsync
has the following signature.
func beginAsync(_ body: () async throws -> Void) rethrows -> Void
However, I think it is better to forbid body
to throw errors, that is to say, to change its signature to the following one.
func beginAsync(_ body: () async -> Void) -> Void
Even if beginAsync
allows that body
throws errors, it can rethrow ones which are thrown before only first await
call. In following cases, beginAsync
just has to make the program crash when foo
throws an error. It breaks safety by typed propagation for error handing realized by throws/try
.
// throws errors asynchronously
func foo() async throws -> Int { ... }
do {
beginAsync {
let a = try await foo()
// uses `a` here
}
} catch _ {
// never reaches here
}
If beginAsync
forbid body
to throw errors, it can be detected as a compilation error and is possible to fix it as follows.
beginAsync {
do {
let a = try await foo()
// uses `a` here
} catch _ {
// error handling
}
}
And even when we want to write try
calls in beginAsync
before first await
call, those lines can be moved before the beginAsync
call.
// before ( `beginAsync` marked with `rethrows` )
do {
beginAsync {
let a = try bar()
let b = try baz()
let c = await qux(a, b)
// uses `c` here
}
catch _ {
// error handling
}
// after ( `beginAsync` without `rethrows` )
do {
let a = try bar()
let b = try baz()
beginAsync {
let c = await qux(a, b)
// uses `c` here
}
catch _ {
// error handling
}
So the functionalities of beginAsync
seems be kept even if it forbid body
to throw errors.
What do you think about it?