Relax return restrictions.
Change-Id: Ica37ff2ac1e206fb4dfc8448af7ecead2c031dd4
Reviewed-on: https://dart-review.googlesource.com/62220
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Leaf Petersen <leafp@google.com>
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index b470ac2..c4208bf 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -5726,35 +5726,63 @@
var toType = expectedType;
var fromType = expressionType;
-
- if (isArrowFunction) {
- if (_inAsync && toType.flattenFutures(_typeSystem).isVoid) {
- return;
- } else if (toType.isVoid) {
- return;
- }
+ if (_inAsync) {
+ toType = toType.flattenFutures(_typeSystem);
+ fromType = fromType.flattenFutures(_typeSystem);
}
+ // Anything can be returned to `void` in an arrow bodied function
+ // or to `Future<void>` in an async arrow bodied function.
+ if (isArrowFunction && toType.isVoid) {
+ return;
+ }
+
+ // Anything can be returned to `dynamic`, or to `Future<dynamic>` in
+ // an async function.
if (toType.isDynamic) {
return;
}
+ // Anything can be return to `Future<Null>` in an async function
+ if (_inAsync && toType.isDartCoreNull) {
+ return;
+ }
+
+ // If we're not in one of the `void` related special cases
+ // just check assignability.
+ if (!toType.isVoid && !fromType.isVoid) {
+ var checkWithType = (!_inAsync)
+ ? fromType
+ : _typeProvider.futureType.instantiate(<DartType>[fromType]);
+ if (_expressionIsAssignableAtType(
+ returnExpression, checkWithType, expectedType)) {
+ return;
+ }
+ }
+
+ // Void related special cases. If the expression type flattens
+ // to `void`, and the expected type doesn't, then it's an error.
+ // Otherwise:
if (toType.isVoid) {
- if (fromType.isVoid) {
- return;
- }
- if (!_inAsync && fromType.isDynamic ||
- fromType.isDartCoreNull ||
- fromType.isBottom) {
- return;
- }
- } else if (!fromType.isVoid) {
- if (_inAsync) {
- fromType = _typeProvider.futureType
- .instantiate(<DartType>[fromType.flattenFutures(_typeSystem)]);
- }
- if (_expressionIsAssignableAtType(returnExpression, fromType, toType)) {
- return;
+ // In the case that the expected type is `void`
+ if (expectedType.isVoid) {
+ // Valid if the expression type is void, dynamic or Null
+ if (expressionType.isVoid ||
+ expressionType.isDynamic ||
+ expressionType.isDartCoreNull ||
+ expressionType.isBottom) {
+ return;
+ }
+ } else {
+ // The expected type is Future<void> or FutureOr<void>,
+ // and the return is valid if the expression type flattens
+ // to void, dynamic, or Null.
+ if (fromType.isVoid ||
+ fromType.isDynamic ||
+ fromType.isDartCoreNull ||
+ fromType.isBottom) {
+ return;
+ }
}
}
reportTypeError();
diff --git a/pkg/vm/lib/frontend_server.dart b/pkg/vm/lib/frontend_server.dart
index 5c69abf..709d28e 100644
--- a/pkg/vm/lib/frontend_server.dart
+++ b/pkg/vm/lib/frontend_server.dart
@@ -714,7 +714,7 @@
compiler.acceptLastDelta();
await compiler.recompileDelta();
compiler.acceptLastDelta();
- return 0;
+ return;
} finally {
temp.deleteSync(recursive: true);
}
diff --git a/tests/language_2/language_2.status b/tests/language_2/language_2.status
index 227ceb6..fbca329 100644
--- a/tests/language_2/language_2.status
+++ b/tests/language_2/language_2.status
@@ -300,7 +300,6 @@
void/return_future_or_void_sync_error3_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_future_or_void_sync_error4_test/none: MissingStaticWarning # https://github.com/dart-lang/sdk/issues/33218
void/return_future_void_async_error2_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
-void/return_future_void_async_test: StaticWarning # https://github.com/dart-lang/sdk/issues/33218
void/return_void_async_error0_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_void_async_error1_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_void_async_error2_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
diff --git a/tests/language_2/void/return_future_future_or_void_async_test.dart b/tests/language_2/void/return_future_future_or_void_async_test.dart
index 81fb4da..68b65ad 100644
--- a/tests/language_2/void/return_future_future_or_void_async_test.dart
+++ b/tests/language_2/void/return_future_future_or_void_async_test.dart
@@ -8,8 +8,6 @@
void main() {
test1();
- test2();
- test3();
test4();
test5();
test6();
@@ -20,16 +18,6 @@
// Testing that a block bodied async function may have no return
Future<FutureOr<void>> test1() async {}
-// Testing that a block bodied async function may return Future<void>
-Future<FutureOr<void>> test2([bool b]) async {
- return null as Future<void>;
-}
-
-// Testing that a block bodied async function may return FutureOr<void>
-Future<FutureOr<void>> test3([bool b]) async {
- return null as FutureOr<void>;
-}
-
// Testing that a block bodied async function may return Future<FutureOr<void>>
Future<FutureOr<void>> test4([bool b]) async {
return null as Future<FutureOr<void>>;
@@ -54,5 +42,5 @@
// Testing that a block bodied async function may return non-void
// Future values
Future<FutureOr<void>> test8() async {
- return new Future.value(42);
+ return new Future<int>.value(42);
}
diff --git a/tests/language_2/void/return_future_or_void_async_error0_test.dart b/tests/language_2/void/return_future_or_void_async_error0_test.dart
deleted file mode 100644
index c5115a7..0000000
--- a/tests/language_2/void/return_future_or_void_async_error0_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-void voidValue = null;
-
-void main() {
- test();
-}
-
-// Testing that a block bodied function may not return void
-FutureOr<void> test() async {
- return /*@compile-error=unspecified*/ voidValue;
-}
diff --git a/tests/language_2/void/return_future_or_void_async_test.dart b/tests/language_2/void/return_future_or_void_async_test.dart
index dfdf1e7..151f337 100644
--- a/tests/language_2/void/return_future_or_void_async_test.dart
+++ b/tests/language_2/void/return_future_or_void_async_test.dart
@@ -11,8 +11,7 @@
test1();
test2();
test3();
- test4();
- test5();
+ test6();
}
// Testing that a block bodied function may have an empty return
@@ -33,14 +32,7 @@
return null as FutureOr<void>;
}
-// Testing that a block bodied async function may return non-void
-// values
-FutureOr<void> test4() async {
- return 42;
-}
-
-// Testing that a block bodied async function may return non-void
-// Future values
-FutureOr<void> test5() async {
- return new Future.value(42);
+// Testing that a block bodied function may return void
+FutureOr<void> test6() async {
+ return voidValue;
}
diff --git a/tests/language_2/void/return_future_void_async_error2_test.dart b/tests/language_2/void/return_future_void_async_error2_test.dart
deleted file mode 100644
index d31263e..0000000
--- a/tests/language_2/void/return_future_void_async_error2_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-void voidValue = null;
-
-void main() {
- test();
-}
-
-// Testing that a block bodied async function may return void
-Future<void> test() async {
- return /*@compile-error=unspecified*/ voidValue;
-}
diff --git a/tests/language_2/void/return_future_void_async_test.dart b/tests/language_2/void/return_future_void_async_test.dart
index ba3f1f1..dae62ed 100644
--- a/tests/language_2/void/return_future_void_async_test.dart
+++ b/tests/language_2/void/return_future_void_async_test.dart
@@ -34,20 +34,17 @@
return null as FutureOr<void>;
}
-// Testing that a block bodied async function may return non-void
-// values
-Future<void> test4() async {
- return 42;
+// Testing that a block bodied async function may return null
+Future<void> test4([bool b]) async {
+ return null;
}
-// Testing that a block bodied async function may return non-void
-// Future values
-Future<void> test5() async {
- return new Future.value(42);
+// Testing that a block bodied async function may return dynamic
+Future<void> test5([bool b]) async {
+ return null as dynamic;
}
-// Testing that a block bodied async function return nested void
-// Future values
+// Testing that a block bodied async function return void
Future<void> test6() async {
- return null as Future<Future<void>>;
+ return voidValue;
}
diff --git a/tests/language_2/void/return_void_async_error3_test.dart b/tests/language_2/void/return_void_async_error3_test.dart
deleted file mode 100644
index 27e691b..0000000
--- a/tests/language_2/void/return_void_async_error3_test.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-void main() {
- test();
-}
-
-// Testing that a block bodied async function may not return Future<void>
-void test() async {
- return /*@compile-error=unspecified*/ null as Future<void>;
-}
diff --git a/tests/language_2/void/return_void_async_test.dart b/tests/language_2/void/return_void_async_test.dart
index bf10b9c..2f9966b 100644
--- a/tests/language_2/void/return_void_async_test.dart
+++ b/tests/language_2/void/return_void_async_test.dart
@@ -11,6 +11,8 @@
test1();
test2();
test3();
+ test4();
+ test5();
}
// Testing that a block bodied async function may have an empty return
@@ -35,3 +37,13 @@
return voidValue;
}
}
+
+// Testing that a block bodied async function may return Null
+void test4() async {
+ return null;
+}
+
+// Testing that a block bodied async function may return dynamic
+void test5() async {
+ return null as dynamic;
+}