| Index: dart/lib/compiler/implementation/resolver.dart | 
| diff --git a/dart/lib/compiler/implementation/resolver.dart b/dart/lib/compiler/implementation/resolver.dart | 
| index e8a31ab6bedc4d9acf0b7a8c9eec15f06d9910b2..18bda8a82018aea265848aa2063b65997db20b9d 100644 | 
| --- a/dart/lib/compiler/implementation/resolver.dart | 
| +++ b/dart/lib/compiler/implementation/resolver.dart | 
| @@ -36,14 +36,12 @@ class TreeElementMapping implements TreeElements { | 
| } | 
|  | 
| class ResolverTask extends CompilerTask { | 
| -  Queue<ClassElement> toResolve; | 
| - | 
| // Caches the elements of analyzed constructors to make them available | 
| // for inlining in later tasks. | 
| Map<FunctionElement, TreeElements> constructorElements; | 
|  | 
| ResolverTask(Compiler compiler) | 
| -    : super(compiler), toResolve = new Queue<ClassElement>(), | 
| +    : super(compiler), | 
| constructorElements = new Map<FunctionElement, TreeElements>(); | 
|  | 
| String get name() => 'Resolver'; | 
| @@ -141,11 +139,6 @@ class ResolverTask extends CompilerTask { | 
| } | 
| visitBody(visitor, tree.body); | 
|  | 
| -      // Resolve the type annotations encountered in the method. | 
| -      while (!toResolve.isEmpty()) { | 
| -        ClassElement classElement = toResolve.removeFirst(); | 
| -        classElement.ensureResolved(compiler); | 
| -      } | 
| if (isConstructor) { | 
| constructorElements[element] = visitor.mapping; | 
| } | 
| @@ -168,6 +161,8 @@ class ResolverTask extends CompilerTask { | 
| } | 
| ClassElement defaultClass = defaultType.element; | 
| defaultClass.ensureResolved(compiler); | 
| +    assert(defaultClass.resolutionState == ClassElement.STATE_DONE); | 
| +    assert(defaultClass.supertypeLoadState == ClassElement.STATE_DONE); | 
| if (defaultClass.isInterface()) { | 
| error(node, MessageKind.CANNOT_INSTANTIATE_INTERFACE, | 
| [defaultClass.name]); | 
| @@ -225,27 +220,63 @@ class ResolverTask extends CompilerTask { | 
| return result; | 
| } | 
|  | 
| +  /** | 
| +   * Load and resolve the supertypes of [cls]. | 
| +   * | 
| +   * Warning: do not call this method directly. It should only be | 
| +   * called by [resolveClass] and [ClassSupertypeResolver]. | 
| +   */ | 
| +  void loadSupertypes(ClassElement cls, Node from) { | 
| +    compiler.withCurrentElement(cls, () => measure(() { | 
| +      if (cls.supertypeLoadState == ClassElement.STATE_DONE) return; | 
| +      if (cls.supertypeLoadState == ClassElement.STATE_STARTED) { | 
| +        compiler.reportMessage( | 
| +          compiler.spanFromNode(from), | 
| +          MessageKind.CYCLIC_CLASS_HIERARCHY.error([cls.name]), | 
| +          api.Diagnostic.ERROR); | 
| +        cls.supertypeLoadState = ClassElement.STATE_DONE; | 
| +        cls.allSupertypes = const EmptyLink<Type>().prepend( | 
| +            compiler.objectClass.computeType(compiler)); | 
| +        return; | 
| +      } | 
| +      cls.supertypeLoadState = ClassElement.STATE_STARTED; | 
| +      compiler.withCurrentElement(cls, () { | 
| +        // TODO(ahe): Cache the node in cls. | 
| +        cls.parseNode(compiler).accept(new ClassSupertypeResolver(compiler, | 
| +                                                                  cls)); | 
| +        if (cls.supertypeLoadState != ClassElement.STATE_DONE) { | 
| +          cls.supertypeLoadState = ClassElement.STATE_DONE; | 
| +        } | 
| +      }); | 
| +    })); | 
| +  } | 
| + | 
| +  /** | 
| +   * Resolve the class [element]. | 
| +   * | 
| +   * Before calling this method, [element] was constructed by the | 
| +   * scanner and most fields are null or empty. This method fills in | 
| +   * these fields and also ensure that the supertypes of [element] are | 
| +   * resolved. | 
| +   * | 
| +   * Warning: Do not call this method directly. Instead use | 
| +   * [:element.ensureResolved(compiler):]. | 
| +   */ | 
| void resolveClass(ClassElement element) { | 
| -    if (element.isResolved || element.isBeingResolved) return; | 
| -    element.isBeingResolved = true; | 
| -    measure(() { | 
| +    assert(element.resolutionState == ClassElement.STATE_NOT_STARTED); | 
| +    element.resolutionState = ClassElement.STATE_STARTED; | 
| +    compiler.withCurrentElement(element, () => measure(() { | 
| ClassNode tree = element.parseNode(compiler); | 
| +      loadSupertypes(element, tree); | 
| + | 
| ClassResolverVisitor visitor = | 
| new ClassResolverVisitor(compiler, element); | 
| visitor.visit(tree); | 
| -      element.isBeingResolved = false; | 
| -      element.isResolved = true; | 
| - | 
| -      while (!toResolve.isEmpty()) { | 
| -        ClassElement classElement = toResolve.removeFirst(); | 
| -        classElement.ensureResolved(compiler); | 
| -      } | 
| - | 
| -      checkMembers(element); | 
| -    }); | 
| +      element.resolutionState = ClassElement.STATE_DONE; | 
| +    })); | 
| } | 
|  | 
| -  checkMembers(ClassElement cls) { | 
| +  void checkMembers(ClassElement cls) { | 
| if (cls === compiler.objectClass) return; | 
| cls.forEachMember((holder, member) { | 
| checkAbstractField(member); | 
| @@ -288,7 +319,6 @@ class ResolverTask extends CompilerTask { | 
| api.Diagnostic.INFO); | 
| } | 
|  | 
| - | 
| void checkValidOverride(Element member, Element superMember) { | 
| if (superMember === null) return; | 
| if (member.modifiers.isStatic()) { | 
| @@ -450,7 +480,7 @@ class InitializerResolver { | 
| ClassElement superClass = classElement.superclass; | 
| if (classElement != visitor.compiler.objectClass) { | 
| assert(superClass !== null); | 
| -      assert(superClass.isResolved); | 
| +      assert(superClass.resolutionState == ClassElement.STATE_DONE); | 
| var element = resolveSuperOrThis(constructor, true, true, | 
| const SourceString(''), | 
| Selector.INVOCATION_0, functionNode); | 
| @@ -769,7 +799,7 @@ class TypeResolver { | 
| type = element.computeType(compiler); | 
| } else if (element.isClass()) { | 
| ClassElement cls = element; | 
| -        if (!cls.isResolved) compiler.resolveClass(cls); | 
| +        cls.ensureResolved(compiler); | 
| Link<Type> arguments = | 
| resolveTypeArguments(node, cls.typeVariables, scope, | 
| onFailure, whenResolved); | 
| @@ -1718,6 +1748,18 @@ class TypeDefinitionVisitor extends CommonResolverVisitor<Type> { | 
| } | 
| } | 
|  | 
| +/** | 
| + * The implementation of [ResolverTask.resolveClass]. | 
| + * | 
| + * This visitor has to be extra careful as it is building the basic | 
| + * element information, and cannot safely look at other elements as | 
| + * this may lead to cycles. | 
| + * | 
| + * This visitor can assume that the supertypes have already been | 
| + * resolved, but it cannot call [ResolverTask.resolveClass] directly | 
| + * or indirectly (through [ClassElement.ensureResolved]) for any other | 
| + * types. | 
| + */ | 
| class ClassResolverVisitor extends TypeDefinitionVisitor { | 
| ClassElement get element() => super.element; | 
|  | 
| @@ -1726,7 +1768,7 @@ class ClassResolverVisitor extends TypeDefinitionVisitor { | 
|  | 
| Type visitClassNode(ClassNode node) { | 
| compiler.ensure(element !== null); | 
| -    compiler.ensure(!element.isResolved); | 
| +    compiler.ensure(element.resolutionState == ClassElement.STATE_STARTED); | 
|  | 
| InterfaceType type = element.computeType(compiler); | 
| scope = new TypeDeclarationScope(scope, element); | 
| @@ -1750,22 +1792,20 @@ class ClassResolverVisitor extends TypeDefinitionVisitor { | 
| if (objectElement === null) { | 
| compiler.internalError("Internal error: cannot resolve Object", | 
| node: node); | 
| -      } else if (!objectElement.isResolved) { | 
| -        compiler.resolver.toResolve.add(objectElement); | 
| +      } else { | 
| +        objectElement.ensureResolved(compiler); | 
| } | 
| // TODO(ahe): This should be objectElement.computeType(...). | 
| element.supertype = new InterfaceType(objectElement); | 
| } | 
| -    if (node.defaultClause !== null) { | 
| -      element.defaultClass = visit(node.defaultClause); | 
| -    } | 
| +    assert(element.interfaces === null); | 
| +    Link<Type> interfaces = const EmptyLink<Type>(); | 
| for (Link<Node> link = node.interfaces.nodes; | 
| !link.isEmpty(); | 
| link = link.tail) { | 
| Type interfaceType = visit(link.head); | 
| if (interfaceType !== null && interfaceType.element.isExtendable()) { | 
| -        element.interfaces = | 
| -            element.interfaces.prepend(interfaceType); | 
| +        interfaces = interfaces.prepend(interfaceType); | 
| if (isBlackListed(interfaceType)) { | 
| error(link.head, MessageKind.CANNOT_IMPLEMENT, [interfaceType]); | 
| } | 
| @@ -1773,7 +1813,12 @@ class ClassResolverVisitor extends TypeDefinitionVisitor { | 
| error(link.head, MessageKind.TYPE_NAME_EXPECTED); | 
| } | 
| } | 
| -    calculateAllSupertypes(element, new Set<ClassElement>()); | 
| +    element.interfaces = interfaces; | 
| +    calculateAllSupertypes(element); | 
| + | 
| +    if (node.defaultClause !== null) { | 
| +      element.defaultClass = visit(node.defaultClause); | 
| +    } | 
| addDefaultConstructorIfNeeded(element); | 
| return element.computeType(compiler); | 
| } | 
| @@ -1791,9 +1836,6 @@ class ClassResolverVisitor extends TypeDefinitionVisitor { | 
| error(node, MessageKind.NOT_A_TYPE, [node]); | 
| return null; | 
| } else { | 
| -      if (element.isClass()) { | 
| -        compiler.resolver.toResolve.add(element); | 
| -      } | 
| if (element.isTypeVariable()) { | 
| TypeVariableElement variableElement = element; | 
| return variableElement.type; | 
| @@ -1828,53 +1870,28 @@ class ClassResolverVisitor extends TypeDefinitionVisitor { | 
| return e.computeType(compiler); | 
| } | 
|  | 
| -  Link<Type> getOrCalculateAllSupertypes(ClassElement cls, | 
| -                                         [Set<ClassElement> seen]) { | 
| -    Link<Type> allSupertypes = cls.allSupertypes; | 
| -    if (allSupertypes !== null) return allSupertypes; | 
| -    if (seen === null) { | 
| -      seen = new Set<ClassElement>(); | 
| -    } | 
| -    if (seen.contains(cls)) { | 
| -      error(cls.parseNode(compiler), | 
| -            MessageKind.CYCLIC_CLASS_HIERARCHY, | 
| -            [cls.name]); | 
| -      cls.allSupertypes = const EmptyLink<Type>(); | 
| -    } else { | 
| -      cls.ensureResolved(compiler); | 
| -      calculateAllSupertypes(cls, seen); | 
| -    } | 
| -    return cls.allSupertypes; | 
| -  } | 
| - | 
| -  void calculateAllSupertypes(ClassElement cls, Set<ClassElement> seen) { | 
| +  void calculateAllSupertypes(ClassElement cls) { | 
| // TODO(karlklose): substitute type variables. | 
| // TODO(karlklose): check if type arguments match, if a classelement occurs | 
| //                  more than once in the supertypes. | 
| if (cls.allSupertypes !== null) return; | 
| final Type supertype = cls.supertype; | 
| -    if (seen.contains(cls)) { | 
| -      error(cls.parseNode(compiler), | 
| -            MessageKind.CYCLIC_CLASS_HIERARCHY, | 
| -            [cls.name]); | 
| -      cls.allSupertypes = const EmptyLink<Type>(); | 
| -    } else if (supertype != null) { | 
| -      seen.add(cls); | 
| -      Link<Type> superSupertypes = | 
| -          getOrCalculateAllSupertypes(supertype.element, seen); | 
| +    if (supertype != null) { | 
| +      Link<Type> superSupertypes = supertype.element.allSupertypes; | 
| +      assert(superSupertypes !== null); | 
| Link<Type> supertypes = new Link<Type>(supertype, superSupertypes); | 
| for (Link<Type> interfaces = cls.interfaces; | 
| !interfaces.isEmpty(); | 
| interfaces = interfaces.tail) { | 
| Element element = interfaces.head.element; | 
| -        Link<Type> interfaceSupertypes = | 
| -            getOrCalculateAllSupertypes(element, seen); | 
| +        Link<Type> interfaceSupertypes = element.allSupertypes; | 
| +        assert(superSupertypes !== null); | 
| supertypes = supertypes.reversePrependAll(interfaceSupertypes); | 
| supertypes = supertypes.prepend(interfaces.head); | 
| } | 
| -      seen.remove(cls); | 
| cls.allSupertypes = supertypes; | 
| } else { | 
| +      assert(cls === compiler.objectClass); | 
| cls.allSupertypes = const EmptyLink<Type>(); | 
| } | 
| } | 
| @@ -1915,6 +1932,79 @@ class ClassResolverVisitor extends TypeDefinitionVisitor { | 
| } | 
| } | 
|  | 
| +class ClassSupertypeResolver extends CommonResolverVisitor { | 
| +  Scope context; | 
| +  ClassElement classElement; | 
| + | 
| +  ClassSupertypeResolver(Compiler compiler, ClassElement cls) | 
| +    : context = new TopScope(cls.getLibrary()), | 
| +      this.classElement = cls, | 
| +      super(compiler); | 
| + | 
| +  void loadSupertype(ClassElement element, Node from) { | 
| +    compiler.resolver.loadSupertypes(element, from); | 
| +    element.ensureResolved(compiler); | 
| +  } | 
| + | 
| +  void visitClassNode(ClassNode node) { | 
| +    if (node.superclass === null) { | 
| +      if (classElement !== compiler.objectClass) { | 
| +        loadSupertype(compiler.objectClass, node); | 
| +      } | 
| +    } else { | 
| +      node.superclass.accept(this); | 
| +    } | 
| +    for (Link<Node> link = node.interfaces.nodes; | 
| +         !link.isEmpty(); | 
| +         link = link.tail) { | 
| +      link.head.accept(this); | 
| +    } | 
| +  } | 
| + | 
| +  void visitTypeAnnotation(TypeAnnotation node) { | 
| +    node.typeName.accept(this); | 
| +  } | 
| + | 
| +  void visitIdentifier(Identifier node) { | 
| +    Element element = context.lookup(node.source); | 
| +    if (element === null) { | 
| +      error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]); | 
| +    } else if (!element.impliesType()) { | 
| +      error(node, MessageKind.NOT_A_TYPE, [node]); | 
| +    } else { | 
| +      if (element.isClass()) { | 
| +        loadSupertype(element, node); | 
| +      } else { | 
| +        compiler.reportMessage( | 
| +          compiler.spanFromNode(node), | 
| +          MessageKind.TYPE_NAME_EXPECTED.error([]), | 
| +          api.Diagnostic.ERROR); | 
| +      } | 
| +    } | 
| +  } | 
| + | 
| +  void visitSend(Send node) { | 
| +    Identifier prefix = node.receiver.asIdentifier(); | 
| +    if (prefix === null) { | 
| +      error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]); | 
| +      return; | 
| +    } | 
| +    Element element = context.lookup(prefix.source); | 
| +    if (element === null || element.kind !== ElementKind.PREFIX) { | 
| +      error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]); | 
| +      return; | 
| +    } | 
| +    PrefixElement prefixElement = element; | 
| +    Identifier selector = node.selector.asIdentifier(); | 
| +    var e = prefixElement.lookupLocalMember(selector.source); | 
| +    if (e === null || !e.impliesType()) { | 
| +      error(node.selector, MessageKind.CANNOT_RESOLVE_TYPE, [node.selector]); | 
| +      return; | 
| +    } | 
| +    loadSupertype(e, node); | 
| +  } | 
| +} | 
| + | 
| class VariableDefinitionsVisitor extends CommonResolverVisitor<SourceString> { | 
| VariableDefinitions definitions; | 
| ResolverVisitor resolver; | 
| @@ -2129,7 +2219,6 @@ class ConstructorResolver extends CommonResolverVisitor<Element> { | 
| if (e !== null && e.kind === ElementKind.CLASS) { | 
| ClassElement cls = e; | 
| cls.ensureResolved(compiler); | 
| -      compiler.resolver.toResolve.add(cls); | 
| if (cls.isInterface() && (cls.defaultClass === null)) { | 
| error(selector, MessageKind.CANNOT_INSTANTIATE_INTERFACE, [cls.name]); | 
| } | 
| @@ -2153,7 +2242,6 @@ class ConstructorResolver extends CommonResolverVisitor<Element> { | 
| if (e.kind === ElementKind.CLASS) { | 
| ClassElement cls = e; | 
| cls.ensureResolved(compiler); | 
| -      compiler.resolver.toResolve.add(cls); | 
| if (cls.isInterface() && (cls.defaultClass === null)) { | 
| error(node.receiver, MessageKind.CANNOT_INSTANTIATE_INTERFACE, | 
| [cls.name]); | 
|  |