Fix various bugs and regularize behavior of returns statements in

various kinds of functions.

Closes-bug: #31887
Closes-bug: #30638
Closes-bug: #32233
Closes-bug: #32881
Closes-bug: #31278
Change-Id: I4ebd7e71096d611e189b571ba5de2998dd11c98b
Reviewed-on: https://dart-review.googlesource.com/60300
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Leaf Petersen <leafp@google.com>
This commit is contained in:
Leaf Petersen 2018-06-15 16:07:44 +00:00 committed by commit-bot@chromium.org
parent f1d1da6164
commit 8e9e8e1da0
38 changed files with 870 additions and 93 deletions

View file

@ -4,6 +4,30 @@
### Language
* Numerous corner case bugs around return statements in synchronous and
asynchronous functions fixed. Specifically:
* Issues [31887][issue 31887], [32881][issue 32881]. Future flattening should
not be recursive.
* Issues [30638][issue 30638], [32233][issue 32233]. Incorrect downcast errors
with `FutureOr`
* Issue [32233][issue 32233]. Errors when returning `FutureOr`
* Issue [33218][issue 33218]. Returns in functions with void related types
* Issue [31278][issue 31278]. Incorrect hint on empty returns in async
functions
* An empty `return;` in an async function with return type `Future<Object>` will
not report an error.
* `return exp;` where `exp` has type `void` in an async function is now an error
unless the return type of the function is `void` or `dynamic`.
* Mixed return statements of the form `return;` and `return exp;` are now
allowed when `exp` has type `void`.
[issue 31887]: https://github.com/dart-lang/sdk/issues/31887
[issue 30638]: https://github.com/dart-lang/sdk/issues/30638
[issue 32233]: https://github.com/dart-lang/sdk/issues/32233
[issue 32881]: https://github.com/dart-lang/sdk/issues/32881
[issue 33218]: https://github.com/dart-lang/sdk/issues/33218
[issue 31278]: https://github.com/dart-lang/sdk/issues/31278
#### Strong Mode
### Dart VM
@ -28,7 +52,7 @@
### Language
Inference chooses `void` when combining `Object` or `dynamic` and `void` ([issue
* Inference chooses `void` when combining `Object` or `dynamic` and `void` ([issue
3341]). When combining with other top types, inference now prefers `void`. So
for example, given:

View file

@ -1447,9 +1447,13 @@ class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
@override
DartType flattenFutures(TypeSystem typeSystem) {
// Implement the case: "If T = Future<S> then flatten(T) = flatten(S)."
if (isDartAsyncFuture && typeArguments.isNotEmpty) {
return typeArguments[0].flattenFutures(typeSystem);
// Implement the cases:
// - "If T = FutureOr<S> then flatten(T) = S."
// - "If T = Future<S> then flatten(T) = S."
if (isDartAsyncFutureOr || isDartAsyncFuture) {
return typeArguments.isNotEmpty
? typeArguments[0]
: DynamicTypeImpl.instance;
}
// Implement the case: "Otherwise if T <: Future then let S be a type

View file

@ -1618,6 +1618,57 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
}
}
/**
* Check that return statements without expressions are not in a generative
* constructor and the return type is not assignable to `null`; that is, we
* don't have `return;` if the enclosing method has a non-void containing
* return type.
*
* See [CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR],
* [StaticWarningCode.RETURN_WITHOUT_VALUE], and
* [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE].
*/
void _checkForAllEmptyReturnStatementErrorCodes(
ReturnStatement statement, DartType expectedReturnType) {
if (_inGenerator) {
return;
}
if (_options.strongMode) {
var returnType = _inAsync
? expectedReturnType.flattenFutures(_typeSystem)
: expectedReturnType;
if (returnType.isDynamic ||
returnType.isDartCoreNull ||
returnType.isVoid) {
return;
}
} else {
// TODO(leafp): Delete this non-strong path
if (_inAsync) {
if (expectedReturnType.isDynamic || expectedReturnType.isVoid) {
return;
}
if (expectedReturnType is InterfaceType &&
expectedReturnType.isDartAsyncFuture) {
DartType futureArgument = expectedReturnType.typeArguments[0];
if (futureArgument.isDynamic ||
futureArgument.isDartCoreNull ||
futureArgument.isVoid ||
futureArgument.isObject) {
return;
}
}
} else if (expectedReturnType.isDynamic || expectedReturnType.isVoid) {
return;
}
}
// If we reach here, this is an invalid return
_hasReturnWithoutValue = true;
_errorReporter.reportErrorForNode(
StaticWarningCode.RETURN_WITHOUT_VALUE, statement);
return;
}
/**
* Verify that the given [constructor] declaration does not violate any of the
* error codes relating to the initialization of fields in the enclosing
@ -2307,7 +2358,8 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* Check that return statements without expressions are not in a generative
* constructor and the return type is not assignable to `null`; that is, we
* don't have `return;` if the enclosing method has a return type.
* don't have `return;` if the enclosing method has a non-void containing
* return type.
*
* Check that the return type matches the type of the declared return type in
* the enclosing method or function.
@ -2322,6 +2374,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
? DynamicTypeImpl.instance
: functionType.returnType;
Expression returnExpression = statement.expression;
// RETURN_IN_GENERATIVE_CONSTRUCTOR
bool isGenerativeConstructor(ExecutableElement element) =>
element is ConstructorElement && !element.isFactory;
@ -2336,34 +2389,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
}
// RETURN_WITHOUT_VALUE
if (returnExpression == null) {
if (_inGenerator) {
return;
} else if (_inAsync) {
if (expectedReturnType.isDynamic || expectedReturnType.isVoid) {
return;
}
if (expectedReturnType is InterfaceType &&
expectedReturnType.isDartAsyncFuture) {
DartType futureArgument = expectedReturnType.typeArguments[0];
if (futureArgument.isDynamic ||
futureArgument.isDartCoreNull ||
futureArgument.isVoid ||
futureArgument.isObject) {
return;
}
}
} else if (expectedReturnType.isDynamic ||
expectedReturnType.isVoid ||
(expectedReturnType.isDartCoreNull && _options.strongMode)) {
// TODO(leafp): Empty returns shouldn't be allowed for Null in strong
// mode either once we allow void as a type argument. But for now, the
// only type we can validly infer for f.then((_) {print("hello");}) is
// Future<Null>, so we allow this.
return;
}
_hasReturnWithoutValue = true;
_errorReporter.reportErrorForNode(
StaticWarningCode.RETURN_WITHOUT_VALUE, statement);
_checkForAllEmptyReturnStatementErrorCodes(statement, expectedReturnType);
return;
} else if (_inGenerator) {
// RETURN_IN_GENERATOR
@ -2371,6 +2397,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
CompileTimeErrorCode.RETURN_IN_GENERATOR,
statement,
[_inAsync ? "async*" : "sync*"]);
return;
}
_checkForReturnOfInvalidType(returnExpression, expectedReturnType);
@ -4837,8 +4864,10 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
if (_hasReturnWithoutValue) {
return;
}
if (_returnsWith.isNotEmpty && _returnsWithout.isNotEmpty) {
for (ReturnStatement returnWith in _returnsWith) {
var nonVoidReturnsWith =
_returnsWith.where((stmt) => !getStaticType(stmt.expression).isVoid);
if (nonVoidReturnsWith.isNotEmpty && _returnsWithout.isNotEmpty) {
for (ReturnStatement returnWith in nonVoidReturnsWith) {
_errorReporter.reportErrorForToken(
StaticWarningCode.MIXED_RETURN_TYPES, returnWith.returnKeyword);
}
@ -5647,7 +5676,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
* See [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE].
*/
void _checkForReturnOfInvalidType(
Expression returnExpression, DartType expectedReturnType,
Expression returnExpression, DartType expectedType,
{bool isArrowFunction = false}) {
if (_enclosingFunction == null) {
return;
@ -5658,19 +5687,79 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
// of the return type. So no need to do any further checking.
return;
}
if (_options.strongMode) {
if (returnExpression == null) {
return; // Empty returns are handled elsewhere
}
DartType expressionType = getStaticType(returnExpression);
void reportTypeError() {
String displayName = _enclosingFunction.displayName;
if (displayName.isEmpty) {
_errorReporter.reportTypeErrorForNode(
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE,
returnExpression,
[expressionType, expectedType]);
} else {
_errorReporter.reportTypeErrorForNode(
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE,
returnExpression,
[expressionType, expectedType, displayName]);
}
}
var toType = expectedType;
var fromType = expressionType;
if (isArrowFunction) {
if (_inAsync && toType.flattenFutures(_typeSystem).isVoid) {
return;
} else if (toType.isVoid) {
return;
}
}
if (toType.isDynamic) {
return;
}
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;
}
}
return reportTypeError();
}
// TODO(leafp): Delete this non Dart 2 path
DartType staticReturnType = _computeReturnTypeForMethod(returnExpression);
String displayName = _enclosingFunction.displayName;
void reportTypeError() => _errorReporter.reportTypeErrorForNode(
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE,
returnExpression,
[staticReturnType, expectedReturnType, displayName]);
[staticReturnType, expectedType, displayName]);
void reportTypeErrorFromClosure() => _errorReporter.reportTypeErrorForNode(
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE,
returnExpression,
[staticReturnType, expectedReturnType]);
[staticReturnType, expectedType]);
if (expectedReturnType.isVoid) {
if (expectedType.isVoid) {
if (isArrowFunction) {
// "void f(..) => e" admits all types for "e".
return;
@ -5691,10 +5780,10 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
// TODO(mfairhurst) Make this stricter once codebases are compliant.
final invalidVoidReturn = staticReturnType.isVoid &&
!(expectedReturnType.isVoid || expectedReturnType.isDynamic);
!(expectedType.isVoid || expectedType.isDynamic);
if (!invalidVoidReturn &&
_expressionIsAssignableAtType(
returnExpression, staticReturnType, expectedReturnType)) {
returnExpression, staticReturnType, expectedType)) {
return;
}
if (displayName.isEmpty) {

View file

@ -1186,7 +1186,30 @@ class BestPracticesVerifier extends RecursiveAstVisitor<Object> {
if (body.isGenerator) {
return;
}
// Check that the type is resolvable, and is not "void"
if (_typeSystem is StrongTypeSystemImpl) {
// Check that the type is resolvable, and is not "void"
DartType returnTypeType = returnType.type;
if (returnTypeType == null) {
return;
}
var flattenedType = body.isAsynchronous
? returnTypeType.flattenFutures(_typeSystem)
: returnTypeType;
if (flattenedType.isDynamic ||
flattenedType.isDartCoreNull ||
flattenedType.isVoid) {
return;
}
// Check the block for a return statement, if not, create the hint
if (!ExitDetector.exits(body)) {
_errorReporter.reportErrorForNode(HintCode.MISSING_RETURN, returnType,
[returnTypeType.displayName]);
}
}
// TODO(leafp): Delete this non-strong mode path
// Check that the type is resolvable and not "void"
DartType returnTypeType = returnType.type;
if (returnTypeType == null ||
returnTypeType.isVoid ||

View file

@ -2573,11 +2573,7 @@ import 'dart:async';
FutureOr<void> f(Future f) async {}
''');
await computeAnalysisResult(source);
if (previewDart2) {
assertErrors(source, [HintCode.MISSING_RETURN]);
} else {
assertNoErrors(source);
}
assertNoErrors(source);
verify([source]);
}

View file

@ -43,14 +43,6 @@ class NonErrorResolverTest_Kernel extends NonErrorResolverTest_Driver {
return super.test_ambiguousImport_showCombinator();
}
@override
@failingTest
@notForDart2
test_async_return_flattens_futures() async {
// Only FutureOr is flattened.
return super.test_async_return_flattens_futures();
}
@override
@failingTest
@FastaProblem('https://github.com/dart-lang/sdk/issues/31604')

View file

@ -664,18 +664,6 @@ Future<Null> f() async {}
verify([source]);
}
test_async_future_object_with_return() async {
Source source = addSource('''
import 'dart:async';
Future<Object> f() async {
return;
}
''');
await computeAnalysisResult(source);
assertNoErrors(source);
verify([source]);
}
test_async_future_object_with_return_value() async {
Source source = addSource('''
import 'dart:async';
@ -722,19 +710,6 @@ Future f() async {}
verify([source]);
}
test_async_return_flattens_futures() async {
Source source = addSource('''
import 'dart:async';
Future<int> f() async {
return g();
}
Future<Future<int>> g() => null;
''');
await computeAnalysisResult(source);
assertNoErrors(source);
verify([source]);
}
test_async_with_return() async {
Source source = addSource('''
f() async {
@ -789,14 +764,11 @@ f(list) async* {
}
test_await_flattened() async {
// The analyzer type system over-flattens so it considers `await ffi()` to
// have type `int` - see dartbug.com/31887
var expectedType = enableKernelDriver ? 'Future<int>' : 'int';
Source source = addSource('''
import 'dart:async';
Future<Future<int>> ffi() => null;
f() async {
$expectedType b = await ffi();
Future<int> b = await ffi();
}
''');
await computeAnalysisResult(source);

View file

@ -44,7 +44,7 @@ import 'dart:async';
Future<Object> f() async {}
''');
await computeAnalysisResult(source);
assertNoErrors(source);
assertErrors(source, [HintCode.MISSING_RETURN]);
verify([source]);
}

View file

@ -342,10 +342,10 @@ class StaticTypeAnalyzerTest extends EngineTestCase {
expect(_flatten(futureDynamicType), dynamicType);
// flatten(Future<int>) = int
expect(_flatten(futureIntType), intType);
// flatten(Future<Future>) = dynamic
expect(_flatten(futureFutureDynamicType), dynamicType);
// flatten(Future<Future<int>>) = int
expect(_flatten(futureFutureIntType), intType);
// flatten(Future<Future>) = Future<dynamic>
expect(_flatten(futureFutureDynamicType), futureDynamicType);
// flatten(Future<Future<int>>) = Future<int>
expect(_flatten(futureFutureIntType), futureIntType);
}
void test_flatten_unrelated_types() {
@ -482,7 +482,7 @@ class StaticTypeAnalyzerTest extends EngineTestCase {
_typeProvider.futureType.instantiate(<DartType>[futureIntType]);
Expression node = AstTestFactory
.awaitExpression(_resolvedVariable(futureFutureIntType, 'e'));
expect(_analyze(node), same(intType));
expect(_analyze(node), same(futureIntType));
_listener.assertNoErrors();
}

View file

@ -143,14 +143,13 @@ f(Object x) {
}
test_await_flattened() async {
// The analyzer type system over-flattens - see dartbug.com/31887
await assertErrorsInCode('''
import 'dart:async';
Future<Future<int>> ffi() => null;
f() async {
Future<int> b = await ffi(); // Warning: int not assignable to Future<int>
Future<int> b = await ffi();
}
''', useCFE ? [] : [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
''', []);
}
test_await_simple() async {
@ -921,6 +920,16 @@ class B<E> {}
f(B<A> b) {}''', [StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT]);
}
test_returnOfInvalidType_async_future_future_int_mismatches_future_int() async {
await assertErrorsInCode('''
import 'dart:async';
Future<int> f() async {
return g();
}
Future<Future<int>> g() => null;
''', [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE]);
}
test_returnOfInvalidType_async_future_int_mismatches_future_string() async {
await assertErrorsInCode('''
import 'dart:async';

View file

@ -3672,6 +3672,18 @@ Future<int> f() async {
verify([source]);
}
test_returnWithoutValue_async_future_object_with_return() async {
Source source = addSource('''
import 'dart:async';
Future<Object> f() async {
return;
}
''');
await computeAnalysisResult(source);
assertErrors(source, [StaticWarningCode.RETURN_WITHOUT_VALUE]);
verify([source]);
}
test_returnWithoutValue_factoryConstructor() async {
Source source = addSource("class A { factory A() { return; } }");
await computeAnalysisResult(source);

View file

@ -45,6 +45,26 @@ initializer_super_last_test/cc29: MissingCompileTimeError
initializer_super_last_test/cc30: MissingCompileTimeError
initializer_super_last_test/cc31: MissingCompileTimeError
initializer_super_last_test/cc32: MissingCompileTimeError
void/return_future_future_or_void_async_error0_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_future_future_or_void_sync_error0_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_future_or_future_or_void_sync_error0_test: MissingCompileTimeError
void/return_future_or_future_or_void_sync_error1_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_future_or_void_async_error0_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_future_or_void_sync_error0_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_future_or_void_sync_error1_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_future_or_void_sync_error2_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_future_or_void_sync_error3_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_future_void_async_error0_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_future_void_async_error1_test: MissingCompileTimeError # 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_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
void/return_void_async_error3_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_void_async_error4_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_void_sync_error0_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_void_sync_error1_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_void_sync_error2_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
[ $compiler != app_jitk && $compiler != dartk && $compiler != dartkp && $mode == debug && $runtime == vm ]
built_in_identifier_type_annotation_test/set: Crash # Not supported by legacy VM front-end.
@ -235,6 +255,7 @@ vm/type_vm_test/24: MissingCompileTimeError
vm/type_vm_test/25: MissingCompileTimeError
vm/type_vm_test/26: MissingCompileTimeError
vm/type_vm_test/27: MissingCompileTimeError
void/return_future_future_or_void_sync_error1_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void_block_return_test/00: MissingCompileTimeError # Requires strong mode
void_type_callbacks_test: Skip # Requires strong mode
void_type_function_types_test: Skip # Requires strong mode
@ -270,6 +291,25 @@ implicit_creation/implicit_new_or_const_test: Fail # No support for implicit cre
implicit_creation/implicit_new_prefix_constructor_generic_named_test: Fail # No support for implicit creation.
implicit_creation/implicit_new_prefix_constructor_named_test: Fail # No support for implicit creation.
setter_override2_test/02: MissingCompileTimeError # Issue 14736
void/return_future_future_or_void_async_error0_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_future_future_or_void_async_error1_test/none: MissingStaticWarning # https://github.com/dart-lang/sdk/issues/33218
void/return_future_future_or_void_sync_error0_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_future_or_future_or_void_sync_error1_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_future_or_future_or_void_sync_error2_test/none: MissingStaticWarning # https://github.com/dart-lang/sdk/issues/33218
void/return_future_or_void_async_error0_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
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
void/return_void_async_error3_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_void_async_error4_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_void_async_test: StaticWarning # https://github.com/dart-lang/sdk/issues/33218
void/return_void_sync_error0_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_void_sync_error1_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
void/return_void_sync_error2_test: MissingCompileTimeError # https://github.com/dart-lang/sdk/issues/33218
[ $compiler == app_jit || $compiler == none ]
library_env_test/has_no_mirror_support: RuntimeError, OK

View file

@ -0,0 +1,16 @@
// 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 not return void
Future<FutureOr<void>> test() async {
return /*@compile-error=unspecified*/ voidValue;
}

View file

@ -0,0 +1,14 @@
// 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 have an empty return
Future<FutureOr<void>> test() async {
return; //# none: static type warning
}

View file

@ -0,0 +1,58 @@
// 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() {
test1();
test2();
test3();
test4();
test5();
test6();
test7();
test8();
}
// 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>>;
}
// Testing that a block bodied async function may return Future<Future<void>>
Future<FutureOr<void>> test5([bool b]) async {
return null as Future<Future<void>>;
}
// Testing that a block bodied async function may return FutureOr<Future<void>>
Future<FutureOr<void>> test6([bool b]) async {
return null as FutureOr<Future<void>>;
}
// Testing that a block bodied async function may return non-void
// values
Future<FutureOr<void>> test7() async {
return 42;
}
// Testing that a block bodied async function may return non-void
// Future values
Future<FutureOr<void>> test8() async {
return new Future.value(42);
}

View file

@ -0,0 +1,16 @@
// 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
Future<FutureOr<void>> test() {
return /*@compile-error=unspecified*/ voidValue;
}

View file

@ -0,0 +1,14 @@
// 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 function may not have an empty return
Future<FutureOr<void>> test0() {
return; /*@compile-error=unspecified*/
}

View file

@ -0,0 +1,32 @@
// 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() {
test1();
test2();
test3();
test4();
}
// Testing that a block bodied function may have no return
Future<FutureOr<void>> test1() {}
// Testing that a block bodied function may return Future<void>
Future<FutureOr<void>> test2() {
return null as Future<void>;
}
// Testing that a block bodied function may return FutureOr<void>
Future<FutureOr<void>> test3() {
return null as Future<FutureOr<void>>;
}
// Testing that a block bodied function may return non-void Future values
Future<FutureOr<void>> test4() {
return new Future.value(42);
}

View file

@ -0,0 +1,16 @@
// 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<FutureOr<void>> test() {
return /*@compile-error=unspecified*/ voidValue;
}

View file

@ -0,0 +1,14 @@
// 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 function may have an empty return
FutureOr<FutureOr<void>> test() {
return; //# none: static type warning
}

View file

@ -0,0 +1,50 @@
// 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() {
test1();
test2();
test3();
test4();
test5();
test6();
}
// Testing that a block bodied function may have no return
FutureOr<FutureOr<void>> test1() {}
// Testing that a block bodied function may return Future<void>
FutureOr<FutureOr<void>> test2() {
return null as Future<void>;
}
// Testing that a block bodied function may return FutureOr<void>
FutureOr<FutureOr<void>> test3() {
return null as FutureOr<void>;
}
// Testing that a block bodied function may return Future<void>
FutureOr<FutureOr<void>> test4() {
return null as Future<Future<void>>;
}
// Testing that a block bodied function may return non-void values
FutureOr<FutureOr<void>> test5() {
return 42;
}
// Testing that a block bodied function may return non-void Future values
FutureOr<FutureOr<void>> test6() {
return new Future.value(42);
}
// Testing that a block bodied function may return overly nested Future
// values
FutureOr<FutureOr<void>> test() {
return null as Future<Future<Future<void>>>;
}

View file

@ -0,0 +1,16 @@
// 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;
}

View file

@ -0,0 +1,46 @@
// 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() {
test0();
test1();
test2();
test3();
test4();
test5();
}
// Testing that a block bodied function may have an empty return
FutureOr<void> test0() async {
return;
}
// Testing that a block bodied function may have no return
FutureOr<void> test1() async {}
// Testing that a block bodied function may return Future<void>
FutureOr<void> test2() async {
return null as Future<void>;
}
// Testing that a block bodied function may return FutureOr<void>
FutureOr<void> test3() async {
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);
}

View file

@ -0,0 +1,16 @@
// 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() {
return /*@compile-error=unspecified*/ voidValue;
}

View file

@ -0,0 +1,14 @@
// 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 function may not have an empty return
FutureOr<void> test() {
return; //# none: static type warning
}

View file

@ -0,0 +1,44 @@
// 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() {
test1();
test2();
test3();
test4();
test5();
test6();
}
// Testing that a block bodied function may have no return
FutureOr<void> test1() {}
// Testing that a block bodied function may return Future<void>
FutureOr<void> test2() {
return null as Future<void>;
}
// Testing that a block bodied function may return FutureOr<void>
FutureOr<void> test3() {
return null as FutureOr<void>;
}
// Testing that a block bodied function may return Future<void>
FutureOr<void> test4() {
return null as Future<Future<void>>;
}
// Testing that a block bodied function may return non-void values
FutureOr<void> test5() {
return 42;
}
// Testing that a block bodied function may return non-void Future values
FutureOr<void> test6() {
return new Future.value(42);
}

View file

@ -0,0 +1,16 @@
// 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;
}

View file

@ -0,0 +1,53 @@
// 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() {
test0();
test1();
test2();
test3();
test4();
test5();
test6();
}
// Testing that a block bodied async function may have an empty return
Future<void> test0() async {
return;
}
// Testing that a block bodied async function may have no return
Future<void> test1() async {}
// Testing that a block bodied async function may return Future<void>
Future<void> test2([bool b]) async {
return null as Future<void>;
}
// Testing that a block bodied async function may return FutureOr<void>
Future<void> test3([bool b]) async {
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 non-void
// Future values
Future<void> test5() async {
return new Future.value(42);
}
// Testing that a block bodied async function return nested void
// Future values
Future<void> test6() async {
return null as Future<Future<void>>;
}

View file

@ -0,0 +1,13 @@
// 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.
void main() {
test();
}
// Testing that a block bodied async function may not return non-void non-top
// values
void test() async {
return /*@compile-error=unspecified*/ 3;
}

View file

@ -0,0 +1,14 @@
// 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.
void main() {
test();
}
// Testing that a block bodied async function may not return non-void Object
// values
void test() async {
Object a = 3;
return /*@compile-error=unspecified*/ a;
}

View file

@ -0,0 +1,15 @@
// 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 non-void Future
// values
void test() async {
return /*@compile-error=unspecified*/ null as Future<int>;
}

View file

@ -0,0 +1,14 @@
// 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>;
}

View file

@ -0,0 +1,14 @@
// 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 FutureOr<void>
void test() async {
return /*@compile-error=unspecified*/ null as FutureOr<void>;
}

View file

@ -0,0 +1,37 @@
// 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() {
test0();
test1();
test2();
test3();
}
// Testing that a block bodied async function may have an empty return
void test0() async {
return;
}
// Testing that a block bodied async function may have no return
void test1() async {}
// Testing that a block bodied async function may return void
void test2() async {
return voidValue;
}
// Testing that a block bodied async function may have both empty returns
// and void returning paths
void test3([bool b]) async {
if (b == null) {
return;
} else {
return voidValue;
}
}

View file

@ -0,0 +1,12 @@
// 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.
void main() {
test();
}
// Testing that a block bodied function may not return non-void non-top values
void test() {
return /*@compile-error=unspecified*/ 3;
}

View file

@ -0,0 +1,13 @@
// 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.
void main() {
test();
}
// Testing that a block bodied function may not return non-void Object values
void test() {
Object a = 3;
return /*@compile-error=unspecified*/ a;
}

View file

@ -0,0 +1,14 @@
// 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 function may not return FutureOr<void>
void test() {
return /*@compile-error=unspecified*/ null as FutureOr<void>;
}

View file

@ -0,0 +1,35 @@
// 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.
void voidValue = null;
void main() {
test0();
test1();
test2();
test3();
}
// Testing that a block bodied function may have an empty return
void test0() {
return;
}
// Testing that a block bodied function may have no return
void test1() {}
// Testing that a block bodied function may return void
void test2() {
return voidValue;
}
// Testing that a block bodied function may have both empty returns
// and void returning paths
void test3([bool b]) {
if (b == null) {
return;
} else if (b) {
return voidValue;
}
}