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 cb8b6f18e32bcf9265ded33a914a9b5b5405b436..e2cd1d99e4cd89b09e1f8d6d889a9476e8395acb 100644 |
--- a/pkg/analyzer/lib/src/task/strong/checker.dart |
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart |
@@ -197,10 +197,19 @@ class CodeChecker extends RecursiveAstVisitor { |
} |
void checkAssignment(Expression expr, DartType type) { |
+ checkForCast(expr, type); |
+ } |
+ |
+ void checkDeclarationCast(Expression expr, DartType type) { |
+ checkForCast(expr, type, isDeclarationCast: true); |
+ } |
+ |
+ void checkForCast(Expression expr, DartType type, |
+ {bool isDeclarationCast = false}) { |
if (expr is ParenthesizedExpression) { |
- checkAssignment(expr.expression, type); |
+ checkForCast(expr.expression, type); |
} else { |
- _checkImplicitCast(expr, type); |
+ _checkImplicitCast(expr, type, isDeclarationCast: isDeclarationCast); |
} |
} |
@@ -432,7 +441,7 @@ class CodeChecker extends RecursiveAstVisitor { |
// Insert a cast from the sequence's element type to the loop variable's |
// if needed. |
_checkImplicitCast(loopVariable, _getDefiniteType(loopVariable), |
- from: elementType); |
+ from: elementType, isDeclarationCast: true); |
} |
} |
@@ -684,7 +693,7 @@ class CodeChecker extends RecursiveAstVisitor { |
var initializer = variable.initializer; |
if (initializer != null) { |
if (type != null) { |
- checkAssignment(initializer, type.type); |
+ checkDeclarationCast(initializer, type.type); |
} |
} |
} |
@@ -760,10 +769,12 @@ class CodeChecker extends RecursiveAstVisitor { |
/// If [expr] does not require an implicit cast because it is not related to |
/// [to] or is already a subtype of it, does nothing. |
void _checkImplicitCast(Expression expr, DartType to, |
- {DartType from, bool opAssign: false}) { |
+ {DartType from, bool opAssign: false, bool isDeclarationCast: false}) { |
from ??= _getDefiniteType(expr); |
- if (_needsImplicitCast(expr, to, from: from) == true) { |
+ if (_needsImplicitCast(expr, to, |
+ from: from, isDeclarationCast: isDeclarationCast) == |
+ true) { |
_recordImplicitCast(expr, to, from: from, opAssign: opAssign); |
} |
} |
@@ -1062,7 +1073,8 @@ class CodeChecker extends RecursiveAstVisitor { |
/// types are statically incompatible. |
/// |
/// If [from] is omitted, uses the static type of [expr] |
- bool _needsImplicitCast(Expression expr, DartType to, {DartType from}) { |
+ bool _needsImplicitCast(Expression expr, DartType to, |
+ {DartType from, bool isDeclarationCast: false}) { |
from ??= _getDefiniteType(expr); |
if (!_checkNonNullAssignment(expr, to, from)) return false; |
@@ -1074,7 +1086,8 @@ class CodeChecker extends RecursiveAstVisitor { |
if (rules.isSubtypeOf(from, to)) return false; |
// Down cast or legal sideways cast, coercion needed. |
- if (rules.isAssignableTo(from, to)) return true; |
+ if (rules.isAssignableTo(from, to, isDeclarationCast: isDeclarationCast)) |
+ return true; |
// Special case for FutureOr to handle returned values from async functions. |
// In this case, we're more permissive than assignability. |