mirror of
https://github.com/dart-lang/sdk
synced 2024-09-20 23:01:19 +00:00
[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:
parent
3a4aad6b87
commit
34f5c9d0b4
|
@ -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_)>(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(#, #)',
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) &&
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -348,6 +348,7 @@ emits
|
|||
emitted
|
||||
emitting
|
||||
en
|
||||
encapsulation
|
||||
enforce
|
||||
enforced
|
||||
enforces
|
||||
|
|
|
@ -78,6 +78,7 @@ callable
|
|||
camel
|
||||
capitalized
|
||||
casing
|
||||
causal
|
||||
cc
|
||||
ccc
|
||||
charcode
|
||||
|
@ -507,6 +508,7 @@ spurious
|
|||
sqrt
|
||||
squared
|
||||
sssp
|
||||
stacks
|
||||
stashed
|
||||
stat
|
||||
stats
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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() {}
|
|
@ -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 {}
|
|
@ -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>;
|
||||
|
|
|
@ -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>;
|
||||
|
|
39
pkg/front_end/testcases/nnbd/return_async.dart
Normal file
39
pkg/front_end/testcases/nnbd/return_async.dart
Normal 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() {}
|
|
@ -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
|
||||
;
|
33
pkg/front_end/testcases/nnbd/return_async.dart.strong.expect
Normal file
33
pkg/front_end/testcases/nnbd/return_async.dart.strong.expect
Normal 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 {}
|
|
@ -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 {}
|
|
@ -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() {}
|
|
@ -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() {}
|
33
pkg/front_end/testcases/nnbd/return_async.dart.weak.expect
Normal file
33
pkg/front_end/testcases/nnbd/return_async.dart.weak.expect
Normal 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 {}
|
|
@ -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 {}
|
|
@ -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("' */");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
101
pkg/kernel/lib/src/future_value_type.dart
Normal file
101
pkg/kernel/lib/src/future_value_type.dart
Normal 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;
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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].
|
||||
|
|
92
pkg/kernel/test/flatten_test.dart
Normal file
92
pkg/kernel/test/flatten_test.dart
Normal 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}");
|
||||
});
|
||||
});
|
||||
}
|
89
pkg/kernel/test/future_value_type_test.dart
Normal file
89
pkg/kernel/test/future_value_type_test.dart
Normal 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}");
|
||||
});
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue