| 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);
 | 
|      }
 | 
|  
 | 
| 
 |