proposal: sync_throw_in_async
#58920
Labels
area-devexp
For issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages.
devexp-linter
Issues with the analyzer's support for the linter package
linter-lint-proposal
linter-status-pending
P3
A lower priority bug or feature request
type-enhancement
A request for a change that isn't a bug
sync_throw_in_async
.Description
A non-
async
function which returns aFuture
should not also throw synchronously.Details
Users expect functions to be either synchronous or asynchronous, the latter being recognized by returning a
Future
.If a function returns a
Future
, users may choose to callcatchError
on the future, and assume that to catch all errors.However, a non-
async
function which returns aFuture
can also choose to throw synchronously instead ofreturning future containing an error.
Users will likely not expect that, and won't catch the error.
The lint will trigger on a
throw
statement in the body of a non-async
function which (statically) returns aFuture
type.(Does not apply to methods which may return a future only if a type variable ends up bound to a future type. That has its own potential problems, but this lint is not trying to fix those. Such a function is not considered "asynchronous", it's just passing futures around as values.)
Kind
This lint guards against errors by providing consistent and predictable APIs to users, where an asynchronous function (returning a
Future
) always provides its entire result in that future, and doesn't throw independently of that.It means callers don't need two layers of error handling, which they'll most likely forget to do.
Good Examples
Bad Examples
Discussion
This has come up multiple times, and it's a rule that the platform libraries try to enforce (haven't always, and that's also always caused problems).
See #50361 for one example of this behavior not being expected.
It's not a big issue if people use
async
for all functions which interact with futures, but that's not required. (Thediscarded_futures
lint).Discussion checklist
Should not directly affect other lints.
#50361 is one example. I'm sure there have been others.
There are other lints that restrict "something" around async in non-
async
functions (discarded_futures
disallows creating a future in a non-async
function). This lint would recognize non-async
functions with aFuture
return type.It's, slightly surprisingly, not something we have said explicitly,
It's a general recommendation that I've repeated many times, that a function returning a
Future
should return all its errors in that future, but it's not written on theFuture
class, and not easily found in our other async documentation.(Should probably fix that.)
The issue above shows one person hitting this. I have seen others.
The problem is usually subtle, because it only shows if an error happens. Most of the time, no error happens, so you won't recognize the issue. The someone, somewhere, uses your library slightly wrong, and they can't catch the error using
Future.catchError
.The text was updated successfully, but these errors were encountered: