[cfe] Implement new async return rules

Closes #41800
Closes #41900
Closes #42134
Closes #42282
Closes #42236
Closes #42169

Change-Id: Ia994bc07fba4e2342fcb59d44fc77608198a328b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152150
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
This commit is contained in:
Johnni Winther 2020-07-06 07:04:40 +00:00 committed by commit-bot@chromium.org
parent 3a4aad6b87
commit 34f5c9d0b4
34 changed files with 1216 additions and 361 deletions

View file

@ -7541,6 +7541,26 @@ const MessageCode messageReturnWithoutExpression = const MessageCode(
severity: Severity.warning,
message: r"""Must explicitly return a value from a non-void function.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeReturnWithoutExpressionAsync =
messageReturnWithoutExpressionAsync;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageReturnWithoutExpressionAsync = const MessageCode(
"ReturnWithoutExpressionAsync",
message:
r"""A value must be explicitly returned from a non-void async function.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeReturnWithoutExpressionSync =
messageReturnWithoutExpressionSync;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageReturnWithoutExpressionSync = const MessageCode(
"ReturnWithoutExpressionSync",
message:
r"""A value must be explicitly returned from a non-void function.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(Uri uri_)> templateSdkRootNotFound =
const Template<Message Function(Uri uri_)>(

View file

@ -100,7 +100,7 @@ abstract class StaticTypeBase extends ir.Visitor<ir.DartType> {
@override
ir.DartType visitAwaitExpression(ir.AwaitExpression node) {
return typeEnvironment.unfutureType(visitNode(node.operand));
return typeEnvironment.flatten(visitNode(node.operand));
}
@override

View file

@ -3125,7 +3125,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
var gen = emitGeneratorFn((_) => []);
// Return type of an async body is `Future<flatten(T)>`, where T is the
// declared return type.
var returnType = _types.unfutureType(function
var returnType = _types.flatten(function
.computeThisFunctionType(_currentLibrary.nonNullable)
.returnType);
return js.call('#.async(#, #)',

View file

@ -271,7 +271,7 @@ class InferenceVisitor
node.operand, typeContext, true,
isVoidAllowed: !inferrer.isNonNullableByDefault);
DartType inferredType =
inferrer.typeSchemaEnvironment.unfutureType(operandResult.inferredType);
inferrer.typeSchemaEnvironment.flatten(operandResult.inferredType);
node.operand = operandResult.expression..parent = node;
return new ExpressionInferenceResult(inferredType, node);
}
@ -2161,7 +2161,7 @@ class InferenceVisitor
bool typeContextIsMap = node.keyType is! ImplicitTypeArgument;
bool typeContextIsIterable = false;
DartType unfuturedTypeContext =
inferrer.typeSchemaEnvironment.unfutureType(typeContext);
inferrer.typeSchemaEnvironment.flatten(typeContext);
if (!inferrer.isTopLevel && inferenceNeeded) {
// Ambiguous set/map literal
if (unfuturedTypeContext is InterfaceType) {

View file

@ -53,8 +53,13 @@ abstract class ClosureContext {
yieldContext, declaredReturnType, needToInferReturnType);
}
} else if (isAsync) {
returnContext = inferrer.wrapFutureOrType(
inferrer.typeSchemaEnvironment.unfutureType(returnContext));
if (inferrer.isNonNullableByDefault) {
returnContext = inferrer.wrapFutureOrType(
inferrer.computeFutureValueTypeSchema(returnContext));
} else {
returnContext = inferrer.wrapFutureOrType(
inferrer.typeSchemaEnvironment.flatten(returnContext));
}
return new _AsyncClosureContext(
returnContext, declaredReturnType, needToInferReturnType);
} else {
@ -148,58 +153,115 @@ class _SyncClosureContext implements ClosureContext {
void _checkValidReturn(TypeInferrerImpl inferrer, DartType returnType,
ReturnStatement statement, DartType expressionType) {
// The rules for valid returns for functions with [returnType] `T` and
// a return expression with static [expressionType] `S`.
if (statement.expression == null) {
// `return;` is a valid return if T is void, dynamic, or Null.
if (returnType is VoidType ||
returnType is DynamicType ||
returnType == inferrer.coreTypes.nullType) {
// Valid return;
if (inferrer.isNonNullableByDefault) {
if (statement.expression == null) {
// It is a compile-time error if s is `return;`, unless T is void,
// dynamic, or Null.
if (returnType is VoidType ||
returnType is DynamicType ||
returnType == inferrer.coreTypes.nullType) {
// Valid return;
} else {
statement.expression = inferrer.helper.wrapInProblem(
new NullLiteral()..fileOffset = statement.fileOffset,
messageReturnWithoutExpressionSync,
statement.fileOffset,
noLength)
..parent = statement;
}
} else {
statement.expression = inferrer.helper.wrapInProblem(
new NullLiteral()..fileOffset = statement.fileOffset,
messageReturnWithoutExpression,
statement.fileOffset,
noLength)
..parent = statement;
if (_isArrow && returnType is VoidType) {
// For `=> e` it is a compile-time error if T is not void, and it
// would have been a compile-time error to declare the function with
// the body `{ return e; }` rather than `=> e`.
return;
}
if (returnType is VoidType &&
!(expressionType is VoidType ||
expressionType is DynamicType ||
expressionType == inferrer.coreTypes.nullType)) {
// It is a compile-time error if s is `return e;`, T is void, and S is
// neither void, dynamic, nor Null.
statement.expression = inferrer.helper.wrapInProblem(
statement.expression,
messageReturnFromVoidFunction,
statement.expression.fileOffset,
noLength)
..parent = statement;
} else if (!(returnType is VoidType || returnType is DynamicType) &&
expressionType is VoidType) {
// It is a compile-time error if s is `return e;`, T is neither void
// nor dynamic, and S is void.
statement.expression = inferrer.helper.wrapInProblem(
statement.expression,
messageVoidExpression,
statement.expression.fileOffset,
noLength)
..parent = statement;
} else if (expressionType is! VoidType) {
// It is a compile-time error if s is `return e;`, S is not void, and
// S is not assignable to T.
Expression expression = inferrer.ensureAssignable(
_returnContext, expressionType, statement.expression,
fileOffset: statement.expression.fileOffset, isVoidAllowed: true);
statement.expression = expression..parent = statement;
}
}
} else {
void ensureAssignability() {
Expression expression = inferrer.ensureAssignable(
_returnContext, expressionType, statement.expression,
fileOffset: statement.fileOffset, isVoidAllowed: true);
statement.expression = expression..parent = statement;
}
if (_isArrow && returnType is VoidType) {
// Arrow functions are valid if: T is void or return exp; is a valid for
// a block-bodied function.
ensureAssignability();
} else if (returnType is VoidType &&
expressionType is! VoidType &&
expressionType is! DynamicType &&
expressionType != inferrer.coreTypes.nullType) {
// Invalid if T is void and S is not void, dynamic, or Null
statement.expression = inferrer.helper.wrapInProblem(
statement.expression,
messageReturnFromVoidFunction,
statement.expression.fileOffset,
noLength)
..parent = statement;
} else if (expressionType is VoidType &&
returnType is! VoidType &&
returnType is! DynamicType &&
returnType != inferrer.coreTypes.nullType) {
// Invalid if S is void and T is not void, dynamic, or Null.
statement.expression = inferrer.helper.wrapInProblem(
statement.expression,
messageVoidExpression,
statement.expression.fileOffset,
noLength)
..parent = statement;
// The rules for valid returns for functions with [returnType] `T` and
// a return expression with static [expressionType] `S`.
if (statement.expression == null) {
// `return;` is a valid return if T is void, dynamic, or Null.
if (returnType is VoidType ||
returnType is DynamicType ||
returnType == inferrer.coreTypes.nullType) {
// Valid return;
} else {
statement.expression = inferrer.helper.wrapInProblem(
new NullLiteral()..fileOffset = statement.fileOffset,
messageReturnWithoutExpression,
statement.fileOffset,
noLength)
..parent = statement;
}
} else {
ensureAssignability();
void ensureAssignability() {
Expression expression = inferrer.ensureAssignable(
_returnContext, expressionType, statement.expression,
fileOffset: statement.fileOffset, isVoidAllowed: true);
statement.expression = expression..parent = statement;
}
if (_isArrow && returnType is VoidType) {
// Arrow functions are valid if: T is void or return exp; is a valid
// for a block-bodied function.
ensureAssignability();
} else if (returnType is VoidType &&
expressionType is! VoidType &&
expressionType is! DynamicType &&
expressionType != inferrer.coreTypes.nullType) {
// Invalid if T is void and S is not void, dynamic, or Null
statement.expression = inferrer.helper.wrapInProblem(
statement.expression,
messageReturnFromVoidFunction,
statement.expression.fileOffset,
noLength)
..parent = statement;
} else if (expressionType is VoidType &&
returnType is! VoidType &&
returnType is! DynamicType &&
returnType != inferrer.coreTypes.nullType) {
// Invalid if S is void and T is not void, dynamic, or Null.
statement.expression = inferrer.helper.wrapInProblem(
statement.expression,
messageVoidExpression,
statement.expression.fileOffset,
noLength)
..parent = statement;
} else {
ensureAssignability();
}
}
}
}
@ -380,72 +442,159 @@ class _AsyncClosureContext implements ClosureContext {
void _checkValidReturn(TypeInferrerImpl inferrer, DartType returnType,
ReturnStatement statement, DartType expressionType) {
// The rules for valid returns for async functions with [returnType] `T` and
// a return expression with static [expressionType] `S`.
DartType flattenedReturnType =
inferrer.typeSchemaEnvironment.unfutureType(returnType);
if (statement.expression == null) {
// `return;` is a valid return if flatten(T) is void, dynamic, or Null.
if (flattenedReturnType is VoidType ||
flattenedReturnType is DynamicType ||
flattenedReturnType == inferrer.coreTypes.nullType) {
// Valid return;
if (inferrer.isNonNullableByDefault) {
DartType futureValueType =
computeFutureValueType(inferrer.coreTypes, returnType);
if (statement.expression == null) {
// It is a compile-time error if s is `return;`, unless T_v is void,
// dynamic, or Null.
if (futureValueType is VoidType ||
futureValueType is DynamicType ||
futureValueType == inferrer.coreTypes.nullType) {
// Valid return;
} else {
statement.expression = inferrer.helper.wrapInProblem(
new NullLiteral()..fileOffset = statement.fileOffset,
messageReturnWithoutExpressionAsync,
statement.fileOffset,
noLength)
..parent = statement;
}
} else {
statement.expression = inferrer.helper.wrapInProblem(
new NullLiteral()..fileOffset = statement.fileOffset,
messageReturnWithoutExpression,
statement.fileOffset,
noLength)
..parent = statement;
if (_isArrow &&
inferrer.typeSchemaEnvironment.flatten(returnType) is VoidType) {
// For `async => e` it is a compile-time error if flatten(T) is not
// void, and it would have been a compile-time error to declare the
// function with the body `async { return e; }` rather than
// `async => e`.
return;
}
DartType flattenedExpressionType =
inferrer.typeSchemaEnvironment.flatten(expressionType);
if (futureValueType is VoidType &&
!(flattenedExpressionType is VoidType ||
flattenedExpressionType is DynamicType ||
flattenedExpressionType == inferrer.coreTypes.nullType)) {
// It is a compile-time error if s is `return e;`, T_v is void, and
// flatten(S) is neither void, dynamic, Null.
statement.expression = inferrer.helper.wrapInProblem(
new NullLiteral()..fileOffset = statement.fileOffset,
messageReturnFromVoidFunction,
statement.expression.fileOffset,
noLength)
..parent = statement;
} else if (!(futureValueType is VoidType ||
futureValueType is DynamicType) &&
flattenedExpressionType is VoidType) {
// It is a compile-time error if s is `return e;`, T_v is neither void
// nor dynamic, and flatten(S) is void.
statement.expression = inferrer.helper.wrapInProblem(
new NullLiteral()..fileOffset = statement.fileOffset,
messageVoidExpression,
statement.expression.fileOffset,
noLength)
..parent = statement;
/* } else if (flattenedExpressionType is! VoidType &&
!inferrer.isAssignable(futureValueType, expressionType) &&
!inferrer.typeSchemaEnvironment
.performNullabilityAwareSubtypeCheck(
flattenedExpressionType, futureValueType)
.isSubtypeWhenUsingNullabilities()) {
// It is a compile-time error if s is `return e;`, flatten(S) is not
// void, S is not assignable to T_v, and flatten(S) is not a subtype
// of T_v.
statement.expression = inferrer.helper.wrapInProblem(
new NullLiteral()..fileOffset = statement.fileOffset,
messageReturnWithoutExpressionAsync,
statement.expression.fileOffset,
noLength)
..parent = statement;*/
} else if (flattenedExpressionType is! VoidType &&
!inferrer.typeSchemaEnvironment
.performNullabilityAwareSubtypeCheck(
flattenedExpressionType, futureValueType)
.isSubtypeWhenUsingNullabilities()) {
// It is a compile-time error if s is `return e;`, flatten(S) is not
// void, S is not assignable to T_v, and flatten(S) is not a subtype
// of T_v.
statement.expression = inferrer.ensureAssignable(
futureValueType, expressionType, statement.expression,
fileOffset: statement.expression.fileOffset,
runtimeCheckedType: _returnContext,
isVoidAllowed: false)
..parent = statement;
}
}
} else {
DartType flattenedExpressionType =
inferrer.typeSchemaEnvironment.unfutureType(expressionType);
void ensureAssignability() {
DartType wrappedType = inferrer.typeSchemaEnvironment
.futureType(flattenedExpressionType, Nullability.nonNullable);
Expression expression = inferrer.ensureAssignable(
computeAssignableType(inferrer, _returnContext, wrappedType),
wrappedType,
statement.expression,
fileOffset: statement.fileOffset,
isVoidAllowed: true,
runtimeCheckedType: _returnContext);
statement.expression = expression..parent = statement;
}
if (_isArrow && flattenedReturnType is VoidType) {
// Arrow functions are valid if: flatten(T) is void or return exp; is
// valid for a block-bodied function.
ensureAssignability();
} else if (returnType is VoidType &&
flattenedExpressionType is! VoidType &&
flattenedExpressionType is! DynamicType &&
flattenedExpressionType != inferrer.coreTypes.nullType) {
// Invalid if T is void and flatten(S) is not void, dynamic, or Null.
statement.expression = inferrer.helper.wrapInProblem(
statement.expression,
messageReturnFromVoidFunction,
statement.expression.fileOffset,
noLength)
..parent = statement;
} else if (flattenedExpressionType is VoidType &&
flattenedReturnType is! VoidType &&
flattenedReturnType is! DynamicType &&
flattenedReturnType != inferrer.coreTypes.nullType) {
// Invalid if flatten(S) is void and flatten(T) is not void, dynamic,
// or Null.
statement.expression = inferrer.helper.wrapInProblem(
statement.expression,
messageVoidExpression,
statement.expression.fileOffset,
noLength)
..parent = statement;
// The rules for valid returns for async functions with [returnType] `T`
// and a return expression with static [expressionType] `S`.
DartType flattenedReturnType =
inferrer.typeSchemaEnvironment.flatten(returnType);
if (statement.expression == null) {
// `return;` is a valid return if flatten(T) is void, dynamic, or Null.
if (flattenedReturnType is VoidType ||
flattenedReturnType is DynamicType ||
flattenedReturnType == inferrer.coreTypes.nullType) {
// Valid return;
} else {
statement.expression = inferrer.helper.wrapInProblem(
new NullLiteral()..fileOffset = statement.fileOffset,
messageReturnWithoutExpression,
statement.fileOffset,
noLength)
..parent = statement;
}
} else {
// The caller will check that the return expression is assignable to the
// return type.
ensureAssignability();
DartType flattenedExpressionType =
inferrer.typeSchemaEnvironment.flatten(expressionType);
void ensureAssignability() {
DartType wrappedType = inferrer.typeSchemaEnvironment
.futureType(flattenedExpressionType, Nullability.nonNullable);
Expression expression = inferrer.ensureAssignable(
computeAssignableType(inferrer, _returnContext, wrappedType),
wrappedType,
statement.expression,
fileOffset: statement.fileOffset,
isVoidAllowed: true,
runtimeCheckedType: _returnContext);
statement.expression = expression..parent = statement;
}
if (_isArrow && flattenedReturnType is VoidType) {
// Arrow functions are valid if: flatten(T) is void or return exp; is
// valid for a block-bodied function.
ensureAssignability();
} else if (returnType is VoidType &&
flattenedExpressionType is! VoidType &&
flattenedExpressionType is! DynamicType &&
flattenedExpressionType != inferrer.coreTypes.nullType) {
// Invalid if T is void and flatten(S) is not void, dynamic, or Null.
statement.expression = inferrer.helper.wrapInProblem(
statement.expression,
messageReturnFromVoidFunction,
statement.expression.fileOffset,
noLength)
..parent = statement;
} else if (flattenedExpressionType is VoidType &&
flattenedReturnType is! VoidType &&
flattenedReturnType is! DynamicType &&
flattenedReturnType != inferrer.coreTypes.nullType) {
// Invalid if flatten(S) is void and flatten(T) is not void, dynamic,
// or Null.
statement.expression = inferrer.helper.wrapInProblem(
statement.expression,
messageVoidExpression,
statement.expression.fileOffset,
noLength)
..parent = statement;
} else {
// The caller will check that the return expression is assignable to
// the return type.
ensureAssignability();
}
}
}
}
@ -488,7 +637,7 @@ class _AsyncClosureContext implements ClosureContext {
// shape FutureOr<T>. We check both branches for FutureOr here: both T
// and Future<T>.
DartType unfuturedExpectedType =
inferrer.typeSchemaEnvironment.unfutureType(contextType);
inferrer.typeSchemaEnvironment.flatten(contextType);
DartType futuredExpectedType = inferrer.wrapFutureType(
unfuturedExpectedType, inferrer.library.nonNullable);
if (inferrer.isAssignable(unfuturedExpectedType, expressionType)) {
@ -514,15 +663,16 @@ class _AsyncClosureContext implements ClosureContext {
// The return expression has to be assignable to the return type
// expectation from the downwards inference context.
if (statement.expression != null) {
if (!inferrer.isAssignable(
computeAssignableType(inferrer, _returnContext, type), type)) {
// Not assignable, use the expectation.
type = inferrer.computeGreatestClosure(_returnContext);
if (!inferrer.isNonNullableByDefault) {
if (statement.expression != null) {
if (!inferrer.isAssignable(
computeAssignableType(inferrer, _returnContext, type), type)) {
// Not assignable, use the expectation.
type = inferrer.computeGreatestClosure(_returnContext);
}
}
}
DartType unwrappedType =
inferrer.typeSchemaEnvironment.unfutureType(type);
DartType unwrappedType = inferrer.typeSchemaEnvironment.flatten(type);
if (inferredType == null) {
inferredType = unwrappedType;
} else {
@ -543,14 +693,26 @@ class _AsyncClosureContext implements ClosureContext {
}
}
inferredType =
inferrer.wrapFutureType(inferredType, inferrer.library.nonNullable);
if (inferrer.isNonNullableByDefault) {
if (!inferrer.typeSchemaEnvironment.isSubtypeOf(
inferredType, _returnContext, SubtypeCheckMode.withNullabilities)) {
// If the inferred return type isn't a subtype of the context, we use
// the context.
inferredType = inferrer.computeGreatestClosure2(_declaredReturnType);
}
inferredType = inferrer.wrapFutureType(
inferrer.typeSchemaEnvironment.flatten(inferredType),
inferrer.library.nonNullable);
} else {
inferredType =
inferrer.wrapFutureType(inferredType, inferrer.library.nonNullable);
if (!inferrer.typeSchemaEnvironment.isSubtypeOf(
inferredType, _returnContext, SubtypeCheckMode.withNullabilities)) {
// If the inferred return type isn't a subtype of the context, we use the
// context.
inferredType = inferrer.computeGreatestClosure2(_declaredReturnType);
if (!inferrer.typeSchemaEnvironment.isSubtypeOf(
inferredType, _returnContext, SubtypeCheckMode.withNullabilities)) {
// If the inferred return type isn't a subtype of the context, we use
// the context.
inferredType = inferrer.computeGreatestClosure2(_declaredReturnType);
}
}
for (int i = 0; i < _returnStatements.length; ++i) {
@ -576,7 +738,7 @@ class _AsyncClosureContext implements ClosureContext {
} else {
returnType = _declaredReturnType;
}
returnType = inferrer.typeSchemaEnvironment.unfutureType(returnType);
returnType = inferrer.typeSchemaEnvironment.flatten(returnType);
if (inferrer.library.isNonNullableByDefault &&
(containsInvalidType(returnType) ||
returnType.isPotentiallyNonNullable) &&

View file

@ -12,17 +12,12 @@ import 'package:front_end/src/fasta/kernel/internal_ast.dart';
import 'package:front_end/src/fasta/type_inference/type_demotion.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:kernel/type_algebra.dart';
import 'package:kernel/type_environment.dart';
import 'package:kernel/src/bounds_checks.dart' show calculateBounds;
import 'package:kernel/src/future_value_type.dart';
import 'package:kernel/src/legacy_erasure.dart';
import '../../base/instrumentation.dart'
@ -3192,6 +3187,22 @@ class TypeInferrerImpl implements TypeInferrer {
class_, nullability, <DartType>[type ?? const DynamicType()]);
}
/// Computes the `futureValueTypeSchema` for the type schema [type].
///
/// This is the same as the [futureValueType] except that this handles
/// the unknown type.
DartType computeFutureValueTypeSchema(DartType type) {
return type.accept1(new FutureValueTypeVisitor(unhandledTypeHandler:
(DartType node, CoreTypes coreTypes,
DartType Function(DartType node, CoreTypes coreTypes) recursor) {
if (node is UnknownType) {
// futureValueTypeSchema(_) = _.
return node;
}
throw new UnsupportedError("Unsupported type '${node.runtimeType}'.");
}), coreTypes);
}
Member _getInterfaceMember(
Class class_, Name name, bool setter, int charOffset) {
Member member = engine.hierarchyBuilder.getCombinedMemberSignatureKernel(

View file

@ -613,6 +613,9 @@ RequiredNamedParameterHasDefaultValueWarning/example: Fail
RethrowNotCatch/example: Fail
ReturnTypeFunctionExpression/analyzerCode: Fail
ReturnTypeFunctionExpression/example: Fail
ReturnWithoutExpressionAsync/analyzerCode: Fail
ReturnWithoutExpressionSync/analyzerCode: Fail
ReturnWithoutExpressionSync/part_wrapped_script: Fail
SdkRootNotFound/analyzerCode: Fail
SdkRootNotFound/example: Fail
SdkSpecificationNotFound/analyzerCode: Fail

View file

@ -3401,6 +3401,18 @@ ReturnWithoutExpression:
analyzerCode: RETURN_WITHOUT_VALUE
declaration: "int foo() { return; }"
ReturnWithoutExpressionSync:
template: "A value must be explicitly returned from a non-void function."
configuration: nnbd-strong
script: |
import "dart:async";
FutureOr<Object?> foo() { return; }
ReturnWithoutExpressionAsync:
template: "A value must be explicitly returned from a non-void async function."
configuration: nnbd-strong
declaration: "Future<int> foo() async { return; }"
ImplicitReturnNull:
template: "A non-null value must be returned since the return type '#type' doesn't allow null."
configuration: nnbd-strong

View file

@ -348,6 +348,7 @@ emits
emitted
emitting
en
encapsulation
enforce
enforced
enforces

View file

@ -78,6 +78,7 @@ callable
camel
capitalized
casing
causal
cc
ccc
charcode
@ -507,6 +508,7 @@ spurious
sqrt
squared
sssp
stacks
stashed
stat
stats

View file

@ -11,19 +11,19 @@ Future<bool> getFutureBool() async {
return true;
}
Future<bool> test1() async => await getNull(); // error
Future<bool> test1() async => await getNull(); // ok
Future<bool> test2() => getNull(); // ok
bool test3() => getNull(); // ok
Future<bool> test4() async => await getFutureNull(); // error
Future<bool> test4() async => await getFutureNull(); // ok
Future<bool> test5() => getFutureNull(); // error
Future<bool> test6() => getFutureBool(); // ok
Future<bool> test7() async => getFutureBool(); // ok
test() async {
Future<bool> test1() async => await getNull(); // error
Future<bool> test1() async => await getNull(); // ok
Future<bool> test2() => getNull(); // ok
bool test3() => getNull(); // ok
Future<bool> test4() async => await getFutureNull(); // error
Future<bool> test4() async => await getFutureNull(); // ok
Future<bool> test5() => getFutureNull(); // error
Future<bool> test6() => getFutureBool(); // ok
Future<bool> test7() async => getFutureBool(); // ok

View file

@ -2,31 +2,11 @@ library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:14:31: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test1() async => await getNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:17:31: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test4() async => await getFutureNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test5() => getFutureNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:23:33: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test1() async => await getNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:26:33: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test4() async => await getFutureNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test5() => getFutureNull(); // error
@ -60,21 +40,15 @@ static method getFutureBool() → asy::Future<core::bool> async {
return true;
}
static method test1() → asy::Future<core::bool> async
return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:14:31: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test1() async => await getNull(); // error
^" in await self::getNull() as{TypeError,ForNonNullableByDefault} FutureOr<core::bool>;
return await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
static method test2() → asy::Future<core::bool>
return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
static method test3() → core::bool
return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
static method test4() → asy::Future<core::bool> async
return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:17:31: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test4() async => await getFutureNull(); // error
^" in await self::getFutureNull() as{TypeError,ForNonNullableByDefault} FutureOr<core::bool>;
return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
static method test5() → asy::Future<core::bool>
return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test5() => getFutureNull(); // error
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@ -84,21 +58,15 @@ static method test7() → asy::Future<core::bool> async
return self::getFutureBool();
static method test() → dynamic async {
function test1() → asy::Future<core::bool> async
return let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:23:33: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test1() async => await getNull(); // error
^" in await self::getNull() as{TypeError,ForNonNullableByDefault} FutureOr<core::bool>;
return await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
function test2() → asy::Future<core::bool>
return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
function test3() → core::bool
return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
function test4() → asy::Future<core::bool> async
return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:26:33: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test4() async => await getFutureNull(); // error
^" in await self::getFutureNull() as{TypeError,ForNonNullableByDefault} FutureOr<core::bool>;
return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
function test5() → asy::Future<core::bool>
return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test5() => getFutureNull(); // error
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@ -106,17 +74,17 @@ static method test() → dynamic async {
return self::getFutureBool();
function test7() → asy::Future<core::bool> async
return self::getFutureBool();
asy::Future<core::bool> var1 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
asy::Future<core::bool> var1 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> var1 = (() async => await getNull())(); // error
^" in (() → asy::Future<dynamic> async => await self::getNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
asy::Future<core::bool> var2 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
core::bool var3 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
asy::Future<core::bool> var4 = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
asy::Future<core::bool> var4 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> var4 = (() async => await getFutureNull())(); // error
^" in (() → asy::Future<dynamic> async => await self::getFutureNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
asy::Future<core::bool> var5 = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
asy::Future<core::bool> var5 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> var5 = (() => getFutureNull())(); // error
^" in (() → asy::Future<dynamic> => self::getFutureNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;

View file

@ -2,31 +2,11 @@ library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:14:31: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test1() async => await getNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:17:31: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test4() async => await getFutureNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test5() => getFutureNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:23:33: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test1() async => await getNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:26:33: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test4() async => await getFutureNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test5() => getFutureNull(); // error
@ -120,12 +100,8 @@ static method test1() → asy::Future<core::bool> /* originally async */ {
try {
#L3:
{
final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:14:31: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test1() async => await getNull(); // error
^";
[yield] let dynamic #t2 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result as{TypeError,ForNonNullableByDefault} FutureOr<core::bool>;
[yield] let dynamic #t1 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
break #L3;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@ -157,12 +133,8 @@ static method test4() → asy::Future<core::bool> /* originally async */ {
try {
#L4:
{
final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:17:31: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test4() async => await getFutureNull(); // error
^";
[yield] let dynamic #t4 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result as{TypeError,ForNonNullableByDefault} FutureOr<core::bool>;
[yield] let dynamic #t2 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
break #L4;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@ -178,7 +150,7 @@ Future<bool> test4() async => await getFutureNull(); // error
return :async_completer.{asy::Completer::future};
}
static method test5() → asy::Future<core::bool>
return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test5() => getFutureNull(); // error
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@ -236,12 +208,8 @@ static method test() → dynamic /* originally async */ {
try {
#L7:
{
final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:23:33: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test1() async => await getNull(); // error
^";
[yield] let dynamic #t7 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result as{TypeError,ForNonNullableByDefault} FutureOr<core::bool>;
[yield] let dynamic #t4 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
break #L7;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@ -273,12 +241,8 @@ static method test() → dynamic /* originally async */ {
try {
#L8:
{
final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:26:33: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test4() async => await getFutureNull(); // error
^";
[yield] let dynamic #t9 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result as{TypeError,ForNonNullableByDefault} FutureOr<core::bool>;
[yield] let dynamic #t5 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
break #L8;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@ -294,7 +258,7 @@ static method test() → dynamic /* originally async */ {
return :async_completer.{asy::Completer::future};
}
function test5() → asy::Future<core::bool>
return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test5() => getFutureNull(); // error
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@ -327,7 +291,7 @@ static method test() → dynamic /* originally async */ {
:async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
return :async_completer.{asy::Completer::future};
}
asy::Future<core::bool> var1 = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
asy::Future<core::bool> var1 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> var1 = (() async => await getNull())(); // error
^" in (() → asy::Future<dynamic> /* originally async */ {
@ -343,7 +307,7 @@ static method test() → dynamic /* originally async */ {
try {
#L10:
{
[yield] let dynamic #t12 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
[yield] let dynamic #t8 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result;
break #L10;
}
@ -361,7 +325,7 @@ static method test() → dynamic /* originally async */ {
}).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
asy::Future<core::bool> var2 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
core::bool var3 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
asy::Future<core::bool> var4 = let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
asy::Future<core::bool> var4 = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> var4 = (() async => await getFutureNull())(); // error
^" in (() → asy::Future<dynamic> /* originally async */ {
@ -377,7 +341,7 @@ static method test() → dynamic /* originally async */ {
try {
#L11:
{
[yield] let dynamic #t14 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
[yield] let dynamic #t10 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result;
break #L11;
}
@ -393,7 +357,7 @@ static method test() → dynamic /* originally async */ {
:async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
return :async_completer.{asy::Completer::future};
}).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
asy::Future<core::bool> var5 = let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
asy::Future<core::bool> var5 = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> var5 = (() => getFutureNull())(); // error
^" in (() → asy::Future<dynamic> => self::getFutureNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;

View file

@ -0,0 +1,12 @@
dynamic getNull() => null;
Future<dynamic> getFutureNull() async {}
Future<bool> getFutureBool() async {}
Future<bool> test1() async => await getNull();
Future<bool> test2() => getNull();
bool test3() => getNull();
Future<bool> test4() async => await getFutureNull();
Future<bool> test5() => getFutureNull();
Future<bool> test6() => getFutureBool();
Future<bool> test7() async => getFutureBool();
test() async {}
main() {}

View file

@ -0,0 +1,12 @@
Future<bool> getFutureBool() async {}
Future<bool> test1() async => await getNull();
Future<bool> test2() => getNull();
Future<bool> test4() async => await getFutureNull();
Future<bool> test5() => getFutureNull();
Future<bool> test6() => getFutureBool();
Future<bool> test7() async => getFutureBool();
Future<dynamic> getFutureNull() async {}
bool test3() => getNull();
dynamic getNull() => null;
main() {}
test() async {}

View file

@ -2,31 +2,11 @@ library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:14:31: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test1() async => await getNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:17:31: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test4() async => await getFutureNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test5() => getFutureNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:23:33: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test1() async => await getNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:26:33: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test4() async => await getFutureNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test5() => getFutureNull(); // error
@ -60,21 +40,15 @@ static method getFutureBool() → asy::Future<core::bool> async {
return true;
}
static method test1() → asy::Future<core::bool> async
return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:14:31: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test1() async => await getNull(); // error
^" in await self::getNull() as{TypeError,ForNonNullableByDefault} FutureOr<core::bool>;
return await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
static method test2() → asy::Future<core::bool>
return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
static method test3() → core::bool
return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
static method test4() → asy::Future<core::bool> async
return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:17:31: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test4() async => await getFutureNull(); // error
^" in await self::getFutureNull() as{TypeError,ForNonNullableByDefault} FutureOr<core::bool>;
return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
static method test5() → asy::Future<core::bool>
return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test5() => getFutureNull(); // error
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@ -84,21 +58,15 @@ static method test7() → asy::Future<core::bool> async
return self::getFutureBool();
static method test() → dynamic async {
function test1() → asy::Future<core::bool> async
return let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:23:33: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test1() async => await getNull(); // error
^" in await self::getNull() as{TypeError,ForNonNullableByDefault} FutureOr<core::bool>;
return await self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
function test2() → asy::Future<core::bool>
return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
function test3() → core::bool
return self::getNull() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
function test4() → asy::Future<core::bool> async
return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:26:33: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test4() async => await getFutureNull(); // error
^" in await self::getFutureNull() as{TypeError,ForNonNullableByDefault} FutureOr<core::bool>;
return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
function test5() → asy::Future<core::bool>
return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test5() => getFutureNull(); // error
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@ -106,17 +74,17 @@ static method test() → dynamic async {
return self::getFutureBool();
function test7() → asy::Future<core::bool> async
return self::getFutureBool();
asy::Future<core::bool> var1 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
asy::Future<core::bool> var1 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> var1 = (() async => await getNull())(); // error
^" in (() → asy::Future<dynamic> async => await self::getNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
asy::Future<core::bool> var2 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
core::bool var3 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
asy::Future<core::bool> var4 = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
asy::Future<core::bool> var4 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> var4 = (() async => await getFutureNull())(); // error
^" in (() → asy::Future<dynamic> async => await self::getFutureNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
asy::Future<core::bool> var5 = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
asy::Future<core::bool> var5 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> var5 = (() => getFutureNull())(); // error
^" in (() → asy::Future<dynamic> => self::getFutureNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;

View file

@ -2,31 +2,11 @@ library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:14:31: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test1() async => await getNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:17:31: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test4() async => await getFutureNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test5() => getFutureNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:23:33: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test1() async => await getNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:26:33: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test4() async => await getFutureNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test5() => getFutureNull(); // error
@ -120,12 +100,8 @@ static method test1() → asy::Future<core::bool> /* originally async */ {
try {
#L3:
{
final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:14:31: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test1() async => await getNull(); // error
^";
[yield] let dynamic #t2 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result as{TypeError,ForNonNullableByDefault} FutureOr<core::bool>;
[yield] let dynamic #t1 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
break #L3;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@ -157,12 +133,8 @@ static method test4() → asy::Future<core::bool> /* originally async */ {
try {
#L4:
{
final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:17:31: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test4() async => await getFutureNull(); // error
^";
[yield] let dynamic #t4 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result as{TypeError,ForNonNullableByDefault} FutureOr<core::bool>;
[yield] let dynamic #t2 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
break #L4;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@ -178,7 +150,7 @@ Future<bool> test4() async => await getFutureNull(); // error
return :async_completer.{asy::Completer::future};
}
static method test5() → asy::Future<core::bool>
return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test5() => getFutureNull(); // error
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@ -236,12 +208,8 @@ static method test() → dynamic /* originally async */ {
try {
#L7:
{
final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:23:33: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test1() async => await getNull(); // error
^";
[yield] let dynamic #t7 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result as{TypeError,ForNonNullableByDefault} FutureOr<core::bool>;
[yield] let dynamic #t4 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
break #L7;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@ -273,12 +241,8 @@ static method test() → dynamic /* originally async */ {
try {
#L8:
{
final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:26:33: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test4() async => await getFutureNull(); // error
^";
[yield] let dynamic #t9 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result as{TypeError,ForNonNullableByDefault} FutureOr<core::bool>;
[yield] let dynamic #t5 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
break #L8;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@ -294,7 +258,7 @@ static method test() → dynamic /* originally async */ {
return :async_completer.{asy::Completer::future};
}
function test5() → asy::Future<core::bool>
return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test5() => getFutureNull(); // error
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@ -327,7 +291,7 @@ static method test() → dynamic /* originally async */ {
:async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
return :async_completer.{asy::Completer::future};
}
asy::Future<core::bool> var1 = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
asy::Future<core::bool> var1 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:31:52: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> var1 = (() async => await getNull())(); // error
^" in (() → asy::Future<dynamic> /* originally async */ {
@ -343,7 +307,7 @@ static method test() → dynamic /* originally async */ {
try {
#L10:
{
[yield] let dynamic #t12 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
[yield] let dynamic #t8 = asy::_awaitHelper(self::getNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result;
break #L10;
}
@ -361,7 +325,7 @@ static method test() → dynamic /* originally async */ {
}).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
asy::Future<core::bool> var2 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<core::bool>;
core::bool var3 = (() → dynamic => self::getNull()).call() as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
asy::Future<core::bool> var4 = let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
asy::Future<core::bool> var4 = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:34:58: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> var4 = (() async => await getFutureNull())(); // error
^" in (() → asy::Future<dynamic> /* originally async */ {
@ -377,7 +341,7 @@ static method test() → dynamic /* originally async */ {
try {
#L11:
{
[yield] let dynamic #t14 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
[yield] let dynamic #t10 = asy::_awaitHelper(self::getFutureNull(), :async_op_then, :async_op_error, :async_op) in null;
:return_value = :result;
break #L11;
}
@ -393,7 +357,7 @@ static method test() → dynamic /* originally async */ {
:async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
return :async_completer.{asy::Completer::future};
}).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
asy::Future<core::bool> var5 = let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
asy::Future<core::bool> var5 = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:35:46: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> var5 = (() => getFutureNull())(); // error
^" in (() → asy::Future<dynamic> => self::getFutureNull()).call() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;

View file

@ -0,0 +1,39 @@
// Copyright (c) 2020, 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.
// This test is derived from `runtime/tests/vm/dart/causal_stacks/utils.dart`.
import 'dart:async';
Future<void> throwSync() {
throw '';
}
Future<void> allYield() async {
await 0;
await allYield2();
}
Future<void> allYield2() async {
await 0;
await allYield3();
}
Future<void> allYield3() async {
await 0;
throwSync();
}
Future<void> customErrorZone() async {
final completer = Completer<void>();
runZonedGuarded(() async {
await allYield();
completer.complete(null);
}, (e, s) {
completer.completeError(e, s);
});
return completer.future;
}
main() {}

View file

@ -0,0 +1,18 @@
library /*isNonNullableByDefault*/;
import self as self;
import "dart:async" as asy;
import "dart:async";
static method throwSync() → asy::Future<void>
;
static method allYield() → asy::Future<void>
;
static method allYield2() → asy::Future<void>
;
static method allYield3() → asy::Future<void>
;
static method customErrorZone() → asy::Future<void>
;
static method main() → dynamic
;

View file

@ -0,0 +1,33 @@
library /*isNonNullableByDefault*/;
import self as self;
import "dart:async" as asy;
import "dart:core" as core;
import "dart:async";
static method throwSync() → asy::Future<void> {
throw "";
}
static method allYield() → asy::Future<void> async {
await 0;
await self::allYield2();
}
static method allYield2() → asy::Future<void> async {
await 0;
await self::allYield3();
}
static method allYield3() → asy::Future<void> async {
await 0;
self::throwSync();
}
static method customErrorZone() → asy::Future<void> async {
final asy::Completer<void> completer = asy::Completer::•<void>();
asy::runZonedGuarded<asy::Future<core::Null?>>(() → asy::Future<core::Null?> async {
await self::allYield();
completer.{asy::Completer::complete}(null);
}, (core::Object e, core::StackTrace s) → core::Null? {
completer.{asy::Completer::completeError}(e, s);
});
return completer.{asy::Completer::future};
}
static method main() → dynamic {}

View file

@ -0,0 +1,160 @@
library /*isNonNullableByDefault*/;
import self as self;
import "dart:async" as asy;
import "dart:core" as core;
import "dart:_internal" as _in;
import "dart:async";
static method throwSync() → asy::Future<void> {
throw "";
}
static method allYield() → asy::Future<void> /* originally async */ {
final asy::_AsyncAwaitCompleter<void> :async_completer = new asy::_AsyncAwaitCompleter::•<void>();
FutureOr<void>? :return_value;
dynamic :async_stack_trace;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L1:
{
[yield] let dynamic #t1 = asy::_awaitHelper(0, :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<core::int>(:result);
[yield] let dynamic #t2 = asy::_awaitHelper(self::allYield2(), :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<void>(:result);
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
:async_completer.{asy::Completer::completeError}(exception, stack_trace);
}
:async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
:async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
return :async_completer.{asy::Completer::future};
}
static method allYield2() → asy::Future<void> /* originally async */ {
final asy::_AsyncAwaitCompleter<void> :async_completer = new asy::_AsyncAwaitCompleter::•<void>();
FutureOr<void>? :return_value;
dynamic :async_stack_trace;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L2:
{
[yield] let dynamic #t3 = asy::_awaitHelper(0, :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<core::int>(:result);
[yield] let dynamic #t4 = asy::_awaitHelper(self::allYield3(), :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<void>(:result);
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
:async_completer.{asy::Completer::completeError}(exception, stack_trace);
}
:async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
:async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
return :async_completer.{asy::Completer::future};
}
static method allYield3() → asy::Future<void> /* originally async */ {
final asy::_AsyncAwaitCompleter<void> :async_completer = new asy::_AsyncAwaitCompleter::•<void>();
FutureOr<void>? :return_value;
dynamic :async_stack_trace;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L3:
{
[yield] let dynamic #t5 = asy::_awaitHelper(0, :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<core::int>(:result);
self::throwSync();
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
:async_completer.{asy::Completer::completeError}(exception, stack_trace);
}
:async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
:async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
return :async_completer.{asy::Completer::future};
}
static method customErrorZone() → asy::Future<void> /* originally async */ {
final asy::_AsyncAwaitCompleter<void> :async_completer = new asy::_AsyncAwaitCompleter::•<void>();
FutureOr<void>? :return_value;
dynamic :async_stack_trace;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L4:
{
final asy::Completer<void> completer = asy::Completer::•<void>();
asy::runZonedGuarded<asy::Future<core::Null?>>(() → asy::Future<core::Null?> /* originally async */ {
final asy::_AsyncAwaitCompleter<core::Null?> :async_completer = new asy::_AsyncAwaitCompleter::•<core::Null?>();
FutureOr<core::Null?>? :return_value;
dynamic :async_stack_trace;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L5:
{
[yield] let dynamic #t6 = asy::_awaitHelper(self::allYield(), :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<void>(:result);
completer.{asy::Completer::complete}(null);
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
:async_completer.{asy::Completer::completeError}(exception, stack_trace);
}
:async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
:async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
return :async_completer.{asy::Completer::future};
}, (core::Object e, core::StackTrace s) → core::Null? {
completer.{asy::Completer::completeError}(e, s);
});
:return_value = completer.{asy::Completer::future};
break #L4;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
:async_completer.{asy::Completer::completeError}(exception, stack_trace);
}
:async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
:async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
return :async_completer.{asy::Completer::future};
}
static method main() → dynamic {}

View file

@ -0,0 +1,8 @@
import 'dart:async';
Future<void> throwSync() {}
Future<void> allYield() async {}
Future<void> allYield2() async {}
Future<void> allYield3() async {}
Future<void> customErrorZone() async {}
main() {}

View file

@ -0,0 +1,8 @@
import 'dart:async';
Future<void> allYield() async {}
Future<void> allYield2() async {}
Future<void> allYield3() async {}
Future<void> customErrorZone() async {}
Future<void> throwSync() {}
main() {}

View file

@ -0,0 +1,33 @@
library /*isNonNullableByDefault*/;
import self as self;
import "dart:async" as asy;
import "dart:core" as core;
import "dart:async";
static method throwSync() → asy::Future<void> {
throw "";
}
static method allYield() → asy::Future<void> async {
await 0;
await self::allYield2();
}
static method allYield2() → asy::Future<void> async {
await 0;
await self::allYield3();
}
static method allYield3() → asy::Future<void> async {
await 0;
self::throwSync();
}
static method customErrorZone() → asy::Future<void> async {
final asy::Completer<void> completer = asy::Completer::•<void>();
asy::runZonedGuarded<asy::Future<core::Null?>>(() → asy::Future<core::Null?> async {
await self::allYield();
completer.{asy::Completer::complete}(null);
}, (core::Object e, core::StackTrace s) → core::Null? {
completer.{asy::Completer::completeError}(e, s);
});
return completer.{asy::Completer::future};
}
static method main() → dynamic {}

View file

@ -0,0 +1,160 @@
library /*isNonNullableByDefault*/;
import self as self;
import "dart:async" as asy;
import "dart:core" as core;
import "dart:_internal" as _in;
import "dart:async";
static method throwSync() → asy::Future<void> {
throw "";
}
static method allYield() → asy::Future<void> /* originally async */ {
final asy::_AsyncAwaitCompleter<void> :async_completer = new asy::_AsyncAwaitCompleter::•<void>();
FutureOr<void>? :return_value;
dynamic :async_stack_trace;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L1:
{
[yield] let dynamic #t1 = asy::_awaitHelper(0, :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<core::int>(:result);
[yield] let dynamic #t2 = asy::_awaitHelper(self::allYield2(), :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<void>(:result);
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
:async_completer.{asy::Completer::completeError}(exception, stack_trace);
}
:async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
:async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
return :async_completer.{asy::Completer::future};
}
static method allYield2() → asy::Future<void> /* originally async */ {
final asy::_AsyncAwaitCompleter<void> :async_completer = new asy::_AsyncAwaitCompleter::•<void>();
FutureOr<void>? :return_value;
dynamic :async_stack_trace;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L2:
{
[yield] let dynamic #t3 = asy::_awaitHelper(0, :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<core::int>(:result);
[yield] let dynamic #t4 = asy::_awaitHelper(self::allYield3(), :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<void>(:result);
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
:async_completer.{asy::Completer::completeError}(exception, stack_trace);
}
:async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
:async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
return :async_completer.{asy::Completer::future};
}
static method allYield3() → asy::Future<void> /* originally async */ {
final asy::_AsyncAwaitCompleter<void> :async_completer = new asy::_AsyncAwaitCompleter::•<void>();
FutureOr<void>? :return_value;
dynamic :async_stack_trace;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L3:
{
[yield] let dynamic #t5 = asy::_awaitHelper(0, :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<core::int>(:result);
self::throwSync();
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
:async_completer.{asy::Completer::completeError}(exception, stack_trace);
}
:async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
:async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
return :async_completer.{asy::Completer::future};
}
static method customErrorZone() → asy::Future<void> /* originally async */ {
final asy::_AsyncAwaitCompleter<void> :async_completer = new asy::_AsyncAwaitCompleter::•<void>();
FutureOr<void>? :return_value;
dynamic :async_stack_trace;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L4:
{
final asy::Completer<void> completer = asy::Completer::•<void>();
asy::runZonedGuarded<asy::Future<core::Null?>>(() → asy::Future<core::Null?> /* originally async */ {
final asy::_AsyncAwaitCompleter<core::Null?> :async_completer = new asy::_AsyncAwaitCompleter::•<core::Null?>();
FutureOr<core::Null?>? :return_value;
dynamic :async_stack_trace;
(dynamic) → dynamic :async_op_then;
(core::Object, core::StackTrace) → dynamic :async_op_error;
core::int :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L5:
{
[yield] let dynamic #t6 = asy::_awaitHelper(self::allYield(), :async_op_then, :async_op_error, :async_op) in null;
_in::unsafeCast<void>(:result);
completer.{asy::Completer::complete}(null);
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
:async_completer.{asy::Completer::completeError}(exception, stack_trace);
}
:async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
:async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
return :async_completer.{asy::Completer::future};
}, (core::Object e, core::StackTrace s) → core::Null? {
completer.{asy::Completer::completeError}(e, s);
});
:return_value = completer.{asy::Completer::future};
break #L4;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
}
on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
:async_completer.{asy::Completer::completeError}(exception, stack_trace);
}
:async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
:async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
return :async_completer.{asy::Completer::future};
}
static method main() → dynamic {}

View file

@ -5483,7 +5483,7 @@ class AwaitExpression extends Expression {
}
DartType getStaticType(StaticTypeContext context) {
return context.typeEnvironment.unfutureType(operand.getStaticType(context));
return context.typeEnvironment.flatten(operand.getStaticType(context));
}
R accept<R>(ExpressionVisitor<R> v) => v.visitAwaitExpression(this);
@ -8310,22 +8310,17 @@ class TypeParameterType extends DartType {
@override
void toTextInternal(AstPrinter printer) {
printer.writeTypeParameterName(parameter);
printer.write(nullabilityToString(declaredNullability));
if (promotedBound != null) {
printer.write('(');
printer.writeTypeParameterName(parameter);
printer.write(nullabilityToString(declaredNullability));
printer.write(" & ");
printer.write(promotedBound.toStringInternal());
printer.write(" /* '");
printer.writeType(promotedBound);
printer.write(')');
printer.write(nullabilityToString(nullability));
} else {
printer.writeTypeParameterName(parameter);
printer.write(nullabilityToString(declaredNullability));
printer.write("' & '");
if (promotedBound is InvalidType) {
printer.write(nullabilityToString(Nullability.undetermined));
} else {
printer.write(nullabilityToString(promotedBound.nullability));
}
printer.write("' = '");
printer.write(nullabilityToString(declaredNullability));
printer.write("' */");
}
}
}

View file

@ -0,0 +1,101 @@
// Copyright (c) 2020, 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 '../ast.dart';
import '../core_types.dart';
DartType computeFutureValueType(CoreTypes coreTypes, DartType type) {
return type.accept1(const FutureValueTypeVisitor(), coreTypes);
}
class FutureValueTypeVisitor implements DartTypeVisitor1<DartType, CoreTypes> {
/// Helper function invoked on unknown implementers of [DartType].
///
/// Its arguments are the unhandled type and the function that can be invoked
/// from within the handler on parts of the unknown type to recursively call
/// the visitor. If not set, an exception is thrown then an unhandled
/// implementer of [DartType] is encountered.
final DartType Function(DartType node, CoreTypes coreTypes,
DartType Function(DartType node, CoreTypes coreTypes) recursor)
unhandledTypeHandler;
const FutureValueTypeVisitor({this.unhandledTypeHandler});
DartType visit(DartType node, CoreTypes coreTypes) =>
node.accept1(this, coreTypes);
@override
DartType defaultDartType(DartType node, CoreTypes coreTypes) {
if (unhandledTypeHandler == null) {
throw new UnsupportedError("Unsupported type '${node.runtimeType}'.");
} else {
return unhandledTypeHandler(node, coreTypes, visit);
}
}
@override
DartType visitBottomType(BottomType node, CoreTypes coreTypes) {
// Otherwise, for all S, futureValueType(S) = Object?.
return coreTypes.objectNullableRawType;
}
@override
DartType visitDynamicType(DynamicType node, CoreTypes coreTypes) {
// futureValueType(dynamic) = dynamic.
return node;
}
@override
DartType visitFunctionType(FunctionType node, CoreTypes coreTypes) {
// Otherwise, for all S, futureValueType(S) = Object?.
return coreTypes.objectNullableRawType;
}
@override
DartType visitInterfaceType(InterfaceType node, CoreTypes coreTypes) {
if (node.classNode == coreTypes.futureClass) {
// futureValueType(Future<S>) = S, for all S.
return node.typeArguments.single;
}
// Otherwise, for all S, futureValueType(S) = Object?.
return coreTypes.objectNullableRawType;
}
@override
DartType visitFutureOrType(FutureOrType node, CoreTypes coreTypes) {
// futureValueType(FutureOr<S>) = S, for all S.
return node.typeArgument;
}
@override
DartType visitInvalidType(InvalidType node, CoreTypes coreTypes) {
// Return the invalid type itself to continue the encapsulation of the
// error state.
return node;
}
@override
DartType visitNeverType(DartType node, CoreTypes coreTypes) {
// Otherwise, for all S, futureValueType(S) = Object?.
return coreTypes.objectNullableRawType;
}
@override
DartType visitTypeParameterType(DartType node, CoreTypes coreTypes) {
// Otherwise, for all S, futureValueType(S) = Object?.
return coreTypes.objectNullableRawType;
}
@override
DartType visitTypedefType(DartType node, CoreTypes coreTypes) {
// Otherwise, for all S, futureValueType(S) = Object?.
return coreTypes.objectNullableRawType;
}
@override
DartType visitVoidType(DartType node, CoreTypes coreTypes) {
// futureValueType(void) = void.
return node;
}
}

View file

@ -121,6 +121,13 @@ class Env {
_libraryEnvironment =
_libraryEnvironment.extendWithTypeParameters(typeParameters);
}
void withTypeParameters(String typeParameters, void Function() f) {
TypeParserEnvironment oldLibraryEnvironment = _libraryEnvironment;
extendWithTypeParameters(typeParameters);
f();
_libraryEnvironment = oldLibraryEnvironment;
}
}
class TypeParserEnvironment {

View file

@ -423,7 +423,7 @@ class TypeCheckingVisitor
@override
DartType visitAwaitExpression(AwaitExpression node) {
return environment.unfutureType(visitExpression(node.operand));
return environment.flatten(visitExpression(node.operand));
}
@override
@ -993,7 +993,7 @@ class TypeCheckingVisitor
} else {
var type = visitExpression(node.expression);
if (currentAsyncMarker == AsyncMarker.Async) {
type = environment.unfutureType(type);
type = environment.flatten(type);
}
checkAssignable(node.expression, type, currentReturnType);
}

View file

@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
library kernel.type_environment;
import 'package:kernel/type_algebra.dart';
import 'ast.dart';
import 'class_hierarchy.dart';
import 'core_types.dart';
@ -79,27 +81,38 @@ abstract class TypeEnvironment extends Types {
coreTypes.futureClass, nullability, <DartType>[type]);
}
/// Removes a level of `Future<>` types wrapping a type.
///
/// This implements the function `flatten` from the spec, which unwraps a
DartType _withDeclaredNullability(DartType type, Nullability nullability) {
if (type == nullType) return type;
return type.withDeclaredNullability(
uniteNullabilities(type.declaredNullability, nullability));
}
/// Returns the `flatten` of [type] as defined in the spec, which unwraps a
/// layer of Future or FutureOr from a type.
DartType unfutureType(DartType type) {
if (type is FutureOrType) return type.typeArgument;
if (type is InterfaceType) {
if (type.classNode == coreTypes.futureClass) {
return type.typeArguments[0];
}
// It is a compile-time error to implement, extend, or mixin FutureOr so
// we aren't concerned with it. If a class implements multiple
// instantiations of Future, getTypeAsInstanceOf is responsible for
// picking the least one in the sense required by the spec.
DartType flatten(DartType t) {
// if T is S? then flatten(T) = flatten(S)?
// otherwise if T is S* then flatten(T) = flatten(S)*
// -- this is preserve with the calls to [_withDeclaredNullability] below.
// otherwise if T is FutureOr<S> then flatten(T) = S
if (t is FutureOrType) {
return _withDeclaredNullability(t.typeArgument, t.declaredNullability);
}
// otherwise if T <: Future then let S be a type such that T <: Future<S>
// and for all R, if T <: Future<R> then S <: R; then flatten(T) = S
DartType resolved = _resolveTypeParameterType(t);
if (resolved is InterfaceType) {
List<DartType> futureArguments =
getTypeArgumentsAsInstanceOf(type, coreTypes.futureClass);
getTypeArgumentsAsInstanceOf(resolved, coreTypes.futureClass);
if (futureArguments != null) {
return futureArguments[0];
return _withDeclaredNullability(
futureArguments.single, t.declaredNullability);
}
}
return type;
// otherwise flatten(T) = T
return t;
}
/// Returns the non-type parameter type bound of [type].

View file

@ -0,0 +1,92 @@
// Copyright (c) 2019, 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 "package:expect/expect.dart" show Expect;
import 'package:kernel/ast.dart' hide MapEntry;
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/testing/type_parser_environment.dart';
import 'package:kernel/type_environment.dart';
const Set<Test> data = {
const Test('Null', 'Null'),
const Test('Never?', 'Never?'),
const Test('void', 'void'),
const Test('dynamic', 'dynamic'),
const Test('bool', 'bool'),
const Test('bool?', 'bool?'),
const Test('bool*', 'bool*'),
const Test('List<bool>', 'List<bool>'),
const Test('List<bool>?', 'List<bool>?'),
const Test('List<bool>*', 'List<bool>*'),
const Test('FutureOr<bool>', 'bool'),
const Test('FutureOr<bool>?', 'bool?'),
const Test('FutureOr<bool>*', 'bool*'),
const Test('FutureOr<bool?>*', 'bool?'),
const Test('FutureOr<bool?>?', 'bool?'),
const Test('FutureOr<bool*>?', 'bool?'),
const Test('FutureOr<Null>', 'Null'),
const Test('FutureOr<Null>?', 'Null'),
const Test('FutureOr<Null>*', 'Null'),
const Test('Future<bool>', 'bool'),
const Test('Future<bool>?', 'bool?'),
const Test('Future<bool>*', 'bool*'),
const Test('Future<bool?>', 'bool?'),
const Test('Future<bool*>', 'bool*'),
const Test('() ->* bool*', '() ->* bool*'),
const Test('() -> bool*', '() -> bool*'),
const Test('() ->? bool*', '() ->? bool*'),
const Test('() ->* bool', '() ->* bool'),
const Test('() ->? bool', '() ->? bool'),
const Test('() -> bool', '() -> bool'),
const Test('T', 'T', 'T'),
const Test('T?', 'T?', 'T'),
const Test('T*', 'T*', 'T'),
const Test('T', 'T', 'T extends bool'),
const Test('T?', 'T?', 'T extends bool'),
const Test('T*', 'T*', 'T extends bool'),
const Test('T', 'T', 'T extends FutureOr<bool>'),
const Test('T?', 'T?', 'T extends FutureOr<bool>'),
const Test('T*', 'T*', 'T extends FutureOr<bool>'),
const Test('T', 'bool', 'T extends Future<bool>'),
const Test('T?', 'bool?', 'T extends Future<bool>'),
const Test('T*', 'bool*', 'T extends Future<bool>'),
const Test('T & bool', 'T & bool', 'T'),
const Test('T & bool?', 'T & bool?', 'T'),
const Test('T & bool*', 'T & bool*', 'T'),
};
class Test {
final String input;
final String output;
final String typeParameters;
const Test(this.input, this.output, [this.typeParameters]);
}
main() {
Env env = new Env('');
ClassHierarchy classHierarchy =
new ClassHierarchy(env.component, env.coreTypes);
TypeEnvironment typeEnvironment =
new TypeEnvironment(env.coreTypes, classHierarchy);
data.forEach((Test test) {
env.withTypeParameters(test.typeParameters, () {
String input = test.input;
String output = test.output;
DartType inputType = env.parseType(input);
DartType expectedOutputType = env.parseType(output);
DartType actualOutputType = typeEnvironment.flatten(inputType);
print('flatten($inputType) '
'${test.typeParameters != null ? 'with ${test.typeParameters} ' : ''}'
'= $actualOutputType, expected $expectedOutputType');
Expect.equals(
expectedOutputType,
actualOutputType,
"Unexpected flatten of $inputType ('$input'):\n"
"Expected: ${expectedOutputType} ('$output')\n"
"Actual: ${actualOutputType}");
});
});
}

View file

@ -0,0 +1,89 @@
// Copyright (c) 2019, 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 "package:expect/expect.dart" show Expect;
import 'package:kernel/ast.dart' hide MapEntry;
import 'package:kernel/src/future_value_type.dart';
import 'package:kernel/testing/type_parser_environment.dart';
const Map<String, String> data = {
'Null': 'Object?',
'Never': 'Object?',
'Never?': 'Object?',
'void': 'void',
'dynamic': 'dynamic',
'bool': 'Object?',
'bool?': 'Object?',
'bool*': 'Object?',
'List<bool>': 'Object?',
'() -> void': 'Object?',
'<T>(T) -> void': 'Object?',
'X': 'Object?',
'X_extends_FutureInt': 'Object?',
'X_extends_FutureOrInt': 'Object?',
'Future<dynamic>': 'dynamic',
'Future<dynamic>?': 'dynamic',
'Future<dynamic>*': 'dynamic',
'Future<Object>': 'Object',
'Future<Object>?': 'Object',
'Future<Object>*': 'Object',
'Future<int?>': 'int?',
'Future<int?>?': 'int?',
'Future<int?>*': 'int?',
'Future<Future<int>?>': 'Future<int>?',
'Future<Future<int>?>?': 'Future<int>?',
'Future<Future<int>?>*': 'Future<int>?',
'Future<FutureOr<int>?>': 'FutureOr<int>?',
'Future<FutureOr<int>?>?': 'FutureOr<int>?',
'Future<FutureOr<int>?>*': 'FutureOr<int>?',
'Future<Null>': 'Null',
'Future<Null>?': 'Null',
'Future<Null>*': 'Null',
'Future<void>': 'void',
'Future<void>?': 'void',
'Future<void>*': 'void',
'FutureOr<dynamic>': 'dynamic',
'FutureOr<dynamic>?': 'dynamic',
'FutureOr<dynamic>*': 'dynamic',
'FutureOr<Object>': 'Object',
'FutureOr<Object>?': 'Object',
'FutureOr<Object>*': 'Object',
'FutureOr<int?>': 'int?',
'FutureOr<int?>?': 'int?',
'FutureOr<int?>*': 'int?',
'FutureOr<Future<int>?>': 'Future<int>?',
'FutureOr<Future<int>?>?': 'Future<int>?',
'FutureOr<Future<int>?>*': 'Future<int>?',
'FutureOr<FutureOr<int>?>': 'FutureOr<int>?',
'FutureOr<FutureOr<int>?>?': 'FutureOr<int>?',
'FutureOr<FutureOr<int>?>*': 'FutureOr<int>?',
'FutureOr<Null>': 'Null',
'FutureOr<Null>?': 'Null',
'FutureOr<Null>*': 'Null',
'FutureOr<void>': 'void',
'FutureOr<void>?': 'void',
'FutureOr<void>*': 'void',
};
main() {
Env env = new Env('')
..extendWithTypeParameters('X,'
'X_extends_FutureInt extends Future<int>,'
'X_extends_FutureOrInt extends FutureOr<int>');
data.forEach((String input, String output) {
DartType inputType = env.parseType(input);
DartType expectedOutputType = env.parseType(output);
DartType actualOutputType =
computeFutureValueType(env.coreTypes, inputType);
print(
'futureValueType($inputType) = $actualOutputType: $expectedOutputType');
Expect.equals(
expectedOutputType,
actualOutputType,
"Unexpected future value type of $inputType ('$input'):\n"
"Expected: ${expectedOutputType} ('$output')\n"
"Actual: ${actualOutputType}");
});
}

View file

@ -393,7 +393,7 @@ class Server {
'uri': serverAddress.toString(),
};
final file = File.fromUri(Uri.parse(serviceInfoFilenameLocal));
return file.writeAsString(json.encode(serviceInfo));
return file.writeAsString(json.encode(serviceInfo)) as Future<void>;
}
Future<Server> startup() async {

View file

@ -13,14 +13,14 @@ Future<B> f1(A a) async {
// ^^^^^^^^^^^^^^^^
// [analyzer] STATIC_TYPE_WARNING.RETURN_OF_INVALID_TYPE
// ^
// [cfe] A value of type 'Future<A>' can't be assigned to a variable of type 'FutureOr<B>'.
// [cfe] A value of type 'FutureOr<A>' can't be assigned to a variable of type 'B'.
}
Future<B> f2(A a) async => a as FutureOr<A>;
// ^^^^^^^^^^^^^^^^
// [analyzer] STATIC_TYPE_WARNING.RETURN_OF_INVALID_TYPE
// ^
// [cfe] A value of type 'Future<A>' can't be assigned to a variable of type 'FutureOr<B>'.
// [cfe] A value of type 'FutureOr<A>' can't be assigned to a variable of type 'B'.
main() async {
Object b;