Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Unified Diff: pkg/analyzer/lib/src/task/strong/checker.dart

Issue 2801683004: Reify implicit casts for FutureOr (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer/lib/src/task/strong/checker.dart
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 91134c2f558bf9a5bd17219eb60ee654b390a389..84579e91e7923c9a462d02d8c5561010585031c9 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -742,7 +742,7 @@ class CodeChecker extends RecursiveAstVisitor {
{DartType from, bool opAssign: false}) {
from ??= _getDefiniteType(expr);
- if (_needsImplicitCast(expr, to, from: from)) {
+ if (_needsImplicitCast(expr, to, from: from) == true) {
_recordImplicitCast(expr, to, from: from, opAssign: opAssign);
}
}
@@ -841,9 +841,11 @@ class CodeChecker extends RecursiveAstVisitor {
// Stream<T> -> T
expectedType = typeProvider.streamType;
} else {
- // Don't validate return type of async methods.
- // They're handled by the runtime implementation.
- return null;
+ // Future<T> -> FutureOr<T>
+ var typeArg = (type.element == typeProvider.futureType.element)
+ ? type.typeArguments[0]
+ : typeProvider.dynamicType;
+ return typeProvider.futureOrType.instantiate([typeArg]);
}
} else {
if (body.isGenerator) {
@@ -907,9 +909,10 @@ class CodeChecker extends RecursiveAstVisitor {
}
/// Returns true if we need an implicit cast of [expr] from [from] type to
- /// [to] type, otherwise returns false.
+ /// [to] type, returns false if no cast is needed, and returns null if the
+ /// types are statically incompatible.
///
- /// If [from] is omitted, uses the static type of [expr].
+ /// If [from] is omitted, uses the static type of [expr]
bool _needsImplicitCast(Expression expr, DartType to, {DartType from}) {
from ??= _getDefiniteType(expr);
@@ -933,10 +936,19 @@ class CodeChecker extends RecursiveAstVisitor {
return true;
}
+ // TODO(vsm): Resolve assignability / implicit cast around FutureOr.
+ // Unwrap FutureOr union to check for a cast.
Leaf 2017/04/05 20:47:27 This will solve the async issue, but will also gen
vsm 2017/04/07 22:23:08 I've cleaned this up to just use assignability.
+ if (to.element == typeProvider.futureOrType.element) {
+ var to1 = to.typeArguments[0];
+ var to2 = typeProvider.futureType.instantiate([to1]);
+ return _needsImplicitCast(expr, to1, from: from) == true ||
+ _needsImplicitCast(expr, to2, from: from) == true;
+ }
+
// Anything else is an illegal sideways cast.
// However, these will have been reported already in error_verifier, so we
// don't need to report them again.
- return false;
+ return null;
Leaf 2017/04/05 20:47:27 Is there any reason not to just generate the cast
vsm 2017/04/07 22:23:07 Injecting the cast here spams the error list with
}
void _recordDynamicInvoke(AstNode node, Expression target) {
@@ -953,7 +965,9 @@ class CodeChecker extends RecursiveAstVisitor {
/// the AST node.
void _recordImplicitCast(Expression expr, DartType to,
{DartType from, bool opAssign: false}) {
- assert(rules.isSubtypeOf(to, from));
+ // TODO(vsm): Resolve assignability / implicit cast around FutureOr.
+ assert(rules.isSubtypeOf(to, from) ||
+ to.element == typeProvider.futureOrType.element);
// Inference "casts":
if (expr is Literal) {

Powered by Google App Engine
This is Rietveld 408576698