Sdk: Future<void>/FutureOr<void> require returns?

Created on 7 Mar 2018  Â·  5Comments  Â·  Source: dart-lang/sdk

The following triggers an analysis warning in 2.0.0-dev.32.0:

import 'dart:async';

void returnNothing() {
  return; // OK
}

Future<void> returnNothingInTheFuture() async {
  return; // ERROR: Expecting return.
}

FutureOr<void> returnNothingMaybeInTheFuture() async {
  return; // ERROR: Expecting return.
}

I can silence it with return null; ... but can't that be automatic?

area-language

Most helpful comment

The current situation is clearly just wrong:

import 'dart:async';

void foo1() {
  return;
}

Null foo2() {
  return;
}

Future<void> foo3() async {
  return; // warning • Missing return value after 'return' at test.dart:12:3 • return_without_value                                                                                                                                                            
}

Future<Null> foo4() async {
  return;
}

void main() { }

All 5 comments

Agreed, when return expressionOfTypeT; is allowed in a function Future<T> foo() async .., it is very natural to allow return; in a function Future<void> foo() async ...

We would need a special exception for this, of course, and there may be other cases. We have had some discussions in #32177, and I've added a reference to this issue there.

These are tricky cases, and I don't think we agree entirely on what to say about it.

My personal guiding rules are that:

  • return; and return voidExpression; must be valid in the same cases (if we allow the latter at all, which we have historically done) ...
  • ... and then return; is really just equivalent to return null as void; (if we allow ... as void) ...
  • ... and the typing rules for return voidExpression; says that it's allowed in an async function if Future<void> is assignable to the return type of the function.

The third entry is the general rule for return e;. A return e; is type-correct if Future<flatten(typeOf(e))> is assignable to the return type of the surrounding function. We know that the actual return value is a Future<flatten(returnType)>, so in the async cases here, the actual return object is a Future<void>, and the Future<flatten(typeOf(e))> thing is really a way of saying that the value of e can be used to complete the actually returned future.

So, I would want the second and third examples to be valid, because they would be for return voidFunction();.

We don't currently have a Dart 2 compatible specification for the return; case, so the law is still open.

The current situation is clearly just wrong:

import 'dart:async';

void foo1() {
  return;
}

Null foo2() {
  return;
}

Future<void> foo3() async {
  return; // warning • Missing return value after 'return' at test.dart:12:3 • return_without_value                                                                                                                                                            
}

Future<Null> foo4() async {
  return;
}

void main() { }

I think you can use like this:

import 'dart:async';

void foo1() {
  return;
}

Null foo2() {
  return;
}

Future<void> foo3() async {
  return Future<void>(() {});                                                                                                                                                      
}

Future<Null> foo4() async {
  return Future<Null>(() {});                                                                                                                                                      
}

With recent updates to the rules about returning (esp. https://github.com/dart-lang/language/pull/941), there are no errors in the following:

import 'dart:async';

void foo1() {
  return;
}

Null foo2() {
  return;
}

Future<void> foo3() async {
  return;
}

Future<Null> foo4() async {
  return;
}
Was this page helpful?
0 / 5 - 0 ratings