Description
The gotcha occurs when you return Future<T>
from Future<T> foo async {}
instead of T
and that return is inside a try
block.
https://twitter.com/_eseidel/status/1660092263190650881
https://dartpad.dev/?id=f4c93eb9f9e24d43079cbc859a867894
class ApiException implements Exception {
ApiException();
}
Future<void> inner() async {
throw ApiException();
}
Future<void> _middle() async {
try {
return inner();
} on ApiException catch (e) {
print('inner: $e');
}
}
Future<void> outer() async {
try {
await _middle();
} on ApiException catch (e) {
print('outer: $e');
}
}
void main() async {
await outer();
}
Would love a lint that would have caught that (and saved me -- and clearly others according to responses on that twitter thread) a while of searching for the issue.
Discussion checklist
- List any existing rules this proposal modifies, complements, overlaps or conflicts with.
unawaited_futures
could have some overlap, although it doesn't trigger here.
unnecessary_await_in_return
seems in direct conflict.
-
List any relevant issues (reported here, the [SDK Tracker], or elsewhere).
-
If there's any prior art (e.g., in other linters), please add references here.
https://dcm.dev/docs/teams/rules/common/prefer-return-await/ -
If this proposal corresponds to [Effective Dart] or [Flutter Style Guide] advice, please call it out. (If there isn't any corresponding advice, should there be?)
-
If this proposal is motivated by real-world examples, please provide as many details as you can. Demonstrating potential impact is especially valuable.
Arguably the real bug is that Future<T> foo async {}
allows returning Future<T>
directly at all, since it nominally expects you to return a T
. But presumably that's an intentional language decision.