| Index: compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
|
| diff --git a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
|
| index 1ceed99fccc8289354854a667f95c53060edbe81..2b069c228cbd3bd414b38d2dddd81745ca1e0625 100644
|
| --- a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
|
| +++ b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
|
| @@ -105,6 +105,7 @@ import com.google.dart.compiler.resolver.VariableElement;
|
| import com.google.dart.compiler.type.InterfaceType.Member;
|
|
|
| import java.util.ArrayList;
|
| +import java.util.Arrays;
|
| import java.util.Collection;
|
| import java.util.Collections;
|
| import java.util.Iterator;
|
| @@ -168,13 +169,15 @@ public class TypeAnalyzer implements DartCompilationPhase {
|
| private final InterfaceType intType;
|
| private final Type nullType;
|
| private final InterfaceType functionType;
|
| -
|
| + private final InterfaceType dynamicIteratorType;
|
| +
|
| /**
|
| * Keeps track of the number of nested catches, used to detect re-throws
|
| * outside of any catch block.
|
| */
|
| private int catchDepth = 0;
|
|
|
| +
|
| Analyzer(DartCompilerContext context, CoreTypeProvider typeProvider,
|
| ConcurrentHashMap<ClassElement, List<Element>> unimplementedElements,
|
| Set<ClassElement> diagnosedAbstractClasses) {
|
| @@ -191,6 +194,7 @@ public class TypeAnalyzer implements DartCompilationPhase {
|
| this.intType = typeProvider.getIntType();
|
| this.nullType = typeProvider.getNullType();
|
| this.functionType = typeProvider.getFunctionType();
|
| + this.dynamicIteratorType = typeProvider.getIteratorType(dynamicType);
|
| }
|
|
|
| @VisibleForTesting
|
| @@ -798,6 +802,35 @@ public class TypeAnalyzer implements DartCompilationPhase {
|
|
|
| @Override
|
| public Type visitForInStatement(DartForInStatement node) {
|
| + Type variableType;
|
| + if (node.introducesVariable()) {
|
| + variableType = typeOf(node.getVariableStatement());
|
| + } else {
|
| + variableType = typeOf(node.getIdentifier());
|
| + }
|
| + DartExpression iterableExpression = node.getIterable();
|
| + Type iterableType = typeOf(iterableExpression);
|
| + Member iteratorMember = lookupMember(iterableType, "iterator", iterableExpression);
|
| + if (iteratorMember != null) {
|
| + if (TypeKind.of(iteratorMember.getType()) == TypeKind.FUNCTION) {
|
| + FunctionType iteratorMethod = (FunctionType) iteratorMember.getType();
|
| + InterfaceType asInstanceOf = types.asInstanceOf(iteratorMethod.getReturnType(),
|
| + dynamicIteratorType.getElement());
|
| + if (asInstanceOf != null) {
|
| + checkAssignable(iterableExpression, variableType, asInstanceOf.getArguments().get(0));
|
| + } else {
|
| + InterfaceType expectedIteratorType = dynamicIteratorType.subst(
|
| + Arrays.asList(variableType), dynamicIteratorType.getElement().getTypeParameters());
|
| + typeError(iterableExpression,
|
| + DartCompilerErrorCode.FOR_IN_WITH_INVALID_ITERATOR_RETURN_TYPE,
|
| + expectedIteratorType);
|
| + }
|
| + } else {
|
| + // Not a function
|
| + typeError(iterableExpression, DartCompilerErrorCode.FOR_IN_WITH_ITERATOR_FIELD);
|
| + }
|
| + }
|
| +
|
| return typeAsVoid(node);
|
| }
|
|
|
|
|