Index: pkg/compiler/lib/src/typechecker.dart |
diff --git a/pkg/compiler/lib/src/typechecker.dart b/pkg/compiler/lib/src/typechecker.dart |
index 6e1e6f43c5094876127faeecb71b381da746923b..e46639a707da901c84f6be60172be2fe18c58a91 100644 |
--- a/pkg/compiler/lib/src/typechecker.dart |
+++ b/pkg/compiler/lib/src/typechecker.dart |
@@ -1792,22 +1792,53 @@ class TypeCheckerVisitor extends Visitor<DartType> { |
return const StatementType(); |
} |
- visitAsyncForIn(AsyncForIn node) { |
- analyze(node.expression); |
- analyze(node.body); |
- return const StatementType(); |
- } |
- |
- visitSyncForIn(SyncForIn node) { |
- DartType elementType; |
+ DartType computeForInElementType(ForIn node) { |
VariableDefinitions declaredIdentifier = |
node.declaredIdentifier.asVariableDefinitions(); |
if (declaredIdentifier != null) { |
- elementType = |
+ return |
analyzeWithDefault(declaredIdentifier.type, const DynamicType()); |
} else { |
- elementType = analyze(node.declaredIdentifier); |
+ return analyze(node.declaredIdentifier); |
} |
+ } |
+ |
+ visitAsyncForIn(AsyncForIn node) { |
+ DartType elementType = computeForInElementType(node); |
+ DartType expressionType = analyze(node.expression); |
+ // TODO(johnniwinther): Move this to _CompilerCoreTypes. |
+ compiler.streamClass.ensureResolved(compiler); |
+ DartType streamOfDynamic = coreTypes.streamType(); |
+ if (!types.isAssignable(expressionType, streamOfDynamic)) { |
+ reportMessage(node.expression, |
+ MessageKind.NOT_ASSIGNABLE, |
+ {'fromType': expressionType, 'toType': streamOfDynamic}, |
+ isHint: true); |
+ } else { |
+ InterfaceType interfaceType = |
+ Types.computeInterfaceType(compiler, expressionType); |
+ if (interfaceType != null) { |
+ InterfaceType streamType = |
+ interfaceType.asInstanceOf(compiler.streamClass); |
+ if (streamType != null) { |
+ DartType streamElementType = streamType.typeArguments.first; |
+ if (!types.isAssignable(streamElementType, elementType)) { |
+ reportMessage(node.expression, |
+ MessageKind.FORIN_NOT_ASSIGNABLE, |
+ {'currentType': streamElementType, |
+ 'expressionType': expressionType, |
+ 'elementType': elementType}, |
+ isHint: true); |
+ } |
+ } |
+ } |
+ } |
+ analyze(node.body); |
+ return const StatementType(); |
+ } |
+ |
+ visitSyncForIn(SyncForIn node) { |
+ DartType elementType = computeForInElementType(node); |
DartType expressionType = analyze(node.expression); |
DartType iteratorType = lookupMemberType(node.expression, |
expressionType, Identifiers.iterator, MemberKind.GETTER); |