IssueRaiser

Disallow returning futures from `async` functions.

In an `async` function with return type `Future<T>`, Dart currently allow you to return either a `T` or `Future<T>`. That made (some) sense in Dart 1, where the type system wasn't particularly helpful and we didn't have type inference. Also, it was pretty much an accident of implementation because the return was implemented as completing a `Completer`, and `Completer.complete` accepted both a value and a future. If the `complete` method had only accepted a value, then I'm fairly sure the language wouldn't have allowed returning a future either. In Dart 2, with its inference pushing context types into expressions, the `return` statement accepting a `FutureOr<T>` is more of a liability than an advantage (see, fx, https://github.com/dart-lang/sdk/issues/40856). I suggest that we change Dart to not accept a `Future<T>` in returns in an `async` function. Then the context type of the return expression becomes `T` (the "future return type" of the function). The typing around returns gets significantly simpler. There is no flatten on the expression, and currently an `async` return needs to check whether the returned value is a `Future<T>`, and if so, await it. If `T` is `Object`, then that's always a possibility, so every return needs to dynamically check whether the value is a future, even if the author knows it's not. This is one of the most complicated cases of implicit future handling in the language specification, and we'd just remove all the complication in one fell swoop.

Posted by lrhn on Mar 5, 2020, 10:20 AM

Tags

Related issues

Raise real-world problems, find people facing the same issue, and discuss solutions.3,500 issues0 comments

github (Software)

Disallow returning futures from `async` functions.

lrhnMar 5, 2020, 10:20 AM

In an `async` function with return type `Future<T>`, Dart currently allow you to return either a `T` or `Future<T>`. That made (some) sense in Dart 1, where the type system wasn't particularly helpful and we didn't have type inference. Also, it was pretty much an accident of implementation because the return was implemented as completing a `Completer`, and `Completer.complete` accepted both a value and a future. If the `complete` method had only accepted a value, then I'm fairly sure the language wouldn't have allowed returning a future either. In Dart 2, with its inference pushing context types into expressions, the `return` statement accepting a `FutureOr<T>` is more of a liability than an advantage (see, fx, https://github.com/dart-lang/sdk/issues/40856). I suggest that we change Dart to not accept a `Future<T>` in returns in an `async` function. Then the context type of the return expression becomes `T` (the "future return type" of the function). The typing around returns gets significantly simpler. There is no flatten on the expression, and currently an `async` return needs to check whether the returned value is a `Future<T>`, and if so, await it. If `T` is `Object`, then that's always a possibility, so every return needs to dynamically check whether the value is a future, even if the author knows it's not. This is one of the most complicated cases of implicit future handling in the language specification, and we'd just remove all the complication in one fell swoop.

Comments (0)

No comments yet. Start the discussion.

Comment on this issue