| 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 5ce4099ee2c2f29109d571d22900f96183743212..5cf362e3b62a1e121b624bc2e9bdc1354816ab84 100644
 | 
| --- a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
 | 
| +++ b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
 | 
| @@ -111,6 +111,7 @@ import com.google.dart.compiler.resolver.Element;
 | 
|  import com.google.dart.compiler.resolver.ElementKind;
 | 
|  import com.google.dart.compiler.resolver.Elements;
 | 
|  import com.google.dart.compiler.resolver.FieldElement;
 | 
| +import com.google.dart.compiler.resolver.FunctionAliasElement;
 | 
|  import com.google.dart.compiler.resolver.LibraryElement;
 | 
|  import com.google.dart.compiler.resolver.MethodElement;
 | 
|  import com.google.dart.compiler.resolver.NodeElement;
 | 
| @@ -1398,9 +1399,13 @@ public class TypeAnalyzer implements DartCompilationPhase {
 | 
|  
 | 
|      @Override
 | 
|      public Type visitFunctionTypeAlias(DartFunctionTypeAlias node) {
 | 
| -      if (TypeKind.of(node.getElement().getType()).equals(TypeKind.FUNCTION_ALIAS)) {
 | 
| -        FunctionAliasType type = node.getElement().getType();
 | 
| +      FunctionAliasElement element = node.getElement();
 | 
| +      FunctionAliasType type = element.getType();
 | 
| +      if (TypeKind.of(type) == TypeKind.FUNCTION_ALIAS) {
 | 
|          checkCyclicBounds(type.getElement().getTypeParameters());
 | 
| +        if (hasFunctionTypeAliasSelfReference(element)) {
 | 
| +          onError(node, TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF);
 | 
| +        }
 | 
|        }
 | 
|        return typeAsVoid(node);
 | 
|      }
 | 
| @@ -2266,6 +2271,64 @@ public class TypeAnalyzer implements DartCompilationPhase {
 | 
|        return voidType;
 | 
|      }
 | 
|  
 | 
| +    /**
 | 
| +     * @return <code>true</code> if given {@link FunctionAliasElement} has direct or indirect
 | 
| +     *         reference to itself using other {@link FunctionAliasElement}s.
 | 
| +     */
 | 
| +    private boolean hasFunctionTypeAliasSelfReference(FunctionAliasElement target) {
 | 
| +      Set<FunctionAliasElement> visited = Sets.newHashSet();
 | 
| +      return hasFunctionTypeAliasReference(visited, target, target);
 | 
| +    }
 | 
| +
 | 
| +    /**
 | 
| +     * Checks if "target" is referenced by "current".
 | 
| +     */
 | 
| +    private boolean hasFunctionTypeAliasReference(Set<FunctionAliasElement> visited,
 | 
| +        FunctionAliasElement target, FunctionAliasElement current) {
 | 
| +      FunctionType type = current.getFunctionType();
 | 
| +      // prepare Types directly referenced by "current"
 | 
| +      Set<Type> referencedTypes = Sets.newHashSet();
 | 
| +      if (type != null) {
 | 
| +        // return type
 | 
| +        referencedTypes.add(type.getReturnType());
 | 
| +        // parameters
 | 
| +        referencedTypes.addAll(type.getParameterTypes());
 | 
| +        referencedTypes.addAll(type.getNamedParameterTypes().values());
 | 
| +      }
 | 
| +      // check that referenced types do not have references on "target"
 | 
| +      for (Type referencedType : referencedTypes) {
 | 
| +        if (referencedType != null
 | 
| +            && hasFunctionTypeAliasReference(visited, target, referencedType.getElement())) {
 | 
| +          return true;
 | 
| +        }
 | 
| +      }
 | 
| +      // no
 | 
| +      return false;
 | 
| +    }
 | 
| +
 | 
| +    /**
 | 
| +     * Checks if "target" is referenced by "current".
 | 
| +     */
 | 
| +    private boolean hasFunctionTypeAliasReference(Set<FunctionAliasElement> visited,
 | 
| +        FunctionAliasElement target, Element currentElement) {
 | 
| +      // only if "current" in function type alias
 | 
| +      if (!(currentElement instanceof FunctionAliasElement)) {
 | 
| +        return false;
 | 
| +      }
 | 
| +      FunctionAliasElement current = (FunctionAliasElement) currentElement;
 | 
| +      // found "target"
 | 
| +      if (Objects.equal(target, current)) {
 | 
| +        return true;
 | 
| +      }
 | 
| +      // prevent recursion
 | 
| +      if (visited.contains(current)) {
 | 
| +        return false;
 | 
| +      }
 | 
| +      visited.add(current);
 | 
| +      // check type of "current" function type alias
 | 
| +      return hasFunctionTypeAliasReference(visited, target, current);
 | 
| +    }
 | 
| +
 | 
|      @Override
 | 
|      public Type visitIntegerLiteral(DartIntegerLiteral node) {
 | 
|        return typeOfLiteral(node);
 | 
| 
 |