// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library dart2js.typechecker;

import 'common/names.dart' show Identifiers;
import 'common/resolution.dart' show Resolution;
import 'common/tasks.dart' show CompilerTask;
import 'common.dart';
import 'compiler.dart' show Compiler;
import 'constants/expressions.dart';
import 'constants/values.dart';
import 'common_elements.dart';
import 'elements/resolution_types.dart';
import 'elements/elements.dart'
    show
        AbstractFieldElement,
        AstElement,
        ClassElement,
        ConstructorElement,
        Element,
        Elements,
        EnumClassElement,
        EnumConstantElement,
        ExecutableElement,
        FieldElement,
        FormalElement,
        FunctionElement,
        GetterElement,
        InitializingFormalElement,
        LibraryElement,
        MemberSignature,
        ResolvedAst,
        SetterElement,
        TypeDeclarationElement,
        TypedElement,
        VariableElement;
import 'elements/entities.dart' show AsyncMarker;
import 'elements/names.dart';
import 'enqueue.dart' show DeferredAction;
import 'resolution/class_members.dart' show MembersCreator, ErroneousMember;
import 'resolution/tree_elements.dart' show TreeElements;
import 'tree/tree.dart';
import 'util/util.dart' show Link, LinkBuilder;

class TypeCheckerTask extends CompilerTask {
  final Compiler compiler;
  TypeCheckerTask(Compiler compiler)
      : compiler = compiler,
        super(compiler.measurer);

  String get name => "Type checker";
  DiagnosticReporter get reporter => compiler.reporter;

  void check(AstElement element) {
    if (element.isClass) return;
    if (element.isTypedef) return;
    ResolvedAst resolvedAst = element.resolvedAst;
    reporter.withCurrentElement(element.implementation, () {
      measure(() {
        TypeCheckerVisitor visitor = new TypeCheckerVisitor(
            compiler, resolvedAst.elements, compiler.resolution.types);
        if (element.isField) {
          visitor.analyzingInitializer = true;
          ResolutionDartType type =
              visitor.analyzeVariableTypeAnnotation(resolvedAst.node);
          visitor.analyzeVariableInitializer(element, type, resolvedAst.body);
        } else {
          resolvedAst.node.accept(visitor);
        }
      });
    });
  }
}

/**
 * Class used to report different warnings for different kinds of members.
 */
class MemberKind {
  static const MemberKind METHOD = const MemberKind("method");
  static const MemberKind OPERATOR = const MemberKind("operator");
  static const MemberKind GETTER = const MemberKind("getter");
  static const MemberKind SETTER = const MemberKind("setter");

  final String name;

  const MemberKind(this.name);

  String toString() => name;
}

/**
 * [ElementAccess] represents the access of [element], either as a property
 * access or invocation.
 */
abstract class ElementAccess {
  Element get element;

  String get name => element.name;

  ResolutionDartType computeType(Resolution resolution);

  /// Returns [: true :] if the element can be access as an invocation.
  bool isCallable(Compiler compiler) {
    if (element != null && element.isAbstractField) {
      AbstractFieldElement abstractFieldElement = element;
      if (abstractFieldElement.getter == null) {
        // Setters cannot be invoked as function invocations.
        return false;
      }
    }
    ResolutionInterfaceType functionType =
        compiler.resolution.commonElements.functionType;
    return compiler.resolution.types
        .isAssignable(computeType(compiler.resolution), functionType);
  }
}

/// An access of a instance member.
class MemberAccess extends ElementAccess {
  final MemberSignature member;

  MemberAccess(MemberSignature this.member);

  Element get element => member.declarations.first.element;

  ResolutionDartType computeType(Resolution resolution) => member.type;

  String toString() => 'MemberAccess($member)';
}

/// An access of an unresolved element.
class DynamicAccess implements ElementAccess {
  const DynamicAccess();

  Element get element => null;

  String get name => 'dynamic';

  ResolutionDartType computeType(Resolution resolution) =>
      const ResolutionDynamicType();

  bool isCallable(Compiler compiler) => true;

  String toString() => 'DynamicAccess';
}

/**
 * An access of a resolved top-level or static property or function, or an
 * access of a resolved element through [:this:].
 */
class ResolvedAccess extends ElementAccess {
  final Element element;

  ResolvedAccess(Element this.element) {
    assert(element != null);
  }

  ResolutionDartType computeType(Resolution resolution) {
    if (element.isGetter) {
      GetterElement getter = element;
      ResolutionFunctionType functionType = getter.computeType(resolution);
      return functionType.returnType;
    } else if (element.isSetter) {
      SetterElement setter = element;
      ResolutionFunctionType functionType = setter.computeType(resolution);
      if (functionType.parameterTypes.length != 1) {
        // TODO(johnniwinther,karlklose): this happens for malformed static
        // setters. Treat them the same as instance members.
        return const ResolutionDynamicType();
      }
      return functionType.parameterTypes.first;
    } else if (element.isTypedef || element.isClass) {
      TypeDeclarationElement typeDeclaration = element;
      typeDeclaration.computeType(resolution);
      return typeDeclaration.thisType;
    } else {
      TypedElement typedElement = element;
      typedElement.computeType(resolution);
      return typedElement.type;
    }
  }

  String toString() => 'ResolvedAccess($element)';
}

/// An access to a promoted variable.
class PromotedAccess extends ElementAccess {
  final VariableElement element;
  final ResolutionDartType type;

  PromotedAccess(VariableElement this.element, ResolutionDartType this.type) {
    assert(element != null);
    assert(type != null);
  }

  ResolutionDartType computeType(Resolution resolution) => type;

  String toString() => 'PromotedAccess($element,$type)';
}

/**
 * An access of a resolved top-level or static property or function, or an
 * access of a resolved element through [:this:].
 */
class TypeAccess extends ElementAccess {
  final ResolutionDartType type;
  TypeAccess(ResolutionDartType this.type) {
    assert(type != null);
  }

  Element get element => type.element;

  ResolutionDartType computeType(Resolution resolution) => type;

  String toString() => 'TypeAccess($type)';
}

/**
 * An access of a type literal.
 */
class TypeLiteralAccess extends ElementAccess {
  final ResolutionDartType type;

  TypeLiteralAccess(this.type) {
    assert(type != null);
  }

  Element get element => type.element;

  String get name => type.name;

  ResolutionInterfaceType computeType(Resolution resolution) =>
      resolution.commonElements.typeType;

  String toString() => 'TypeLiteralAccess($type)';
}

/// An access to the 'call' method of a function type.
class FunctionCallAccess implements ElementAccess {
  final Element element;
  final ResolutionDartType type;

  const FunctionCallAccess(this.element, this.type);

  String get name => 'call';

  ResolutionDartType computeType(Resolution resolution) => type;

  bool isCallable(Compiler compiler) => true;

  String toString() => 'FunctionAccess($element, $type)';
}

/// An is-expression that potentially promotes a variable.
class TypePromotion {
  final Send node;
  final VariableElement variable;
  final ResolutionDartType type;
  final List<TypePromotionMessage> messages = <TypePromotionMessage>[];

  TypePromotion(this.node, this.variable, this.type);

  bool get isValid => messages.isEmpty;

  TypePromotion copy() {
    return new TypePromotion(node, variable, type)..messages.addAll(messages);
  }

  void addHint(DiagnosticMessage hint,
      [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
    messages.add(new TypePromotionMessage(hint, infos));
  }

  String toString() {
    return 'Promote ${variable} to ${type}${isValid ? '' : ' (invalid)'}';
  }
}

/// A hint or info message attached to a type promotion.
class TypePromotionMessage {
  DiagnosticMessage hint;
  List<DiagnosticMessage> infos;

  TypePromotionMessage(this.hint, this.infos);
}

class TypeCheckerVisitor extends Visitor<ResolutionDartType> {
  final Compiler compiler;
  final TreeElements elements;
  final Types types;

  Node lastSeenNode;
  ResolutionDartType expectedReturnType;
  AsyncMarker currentAsyncMarker = AsyncMarker.SYNC;

  final ClassElement currentClass;

  /// The immediately enclosing field, method or constructor being analyzed.
  ExecutableElement executableContext;

  CommonElements get commonElements => resolution.commonElements;

  DiagnosticReporter get reporter => compiler.reporter;

  Resolution get resolution => compiler.resolution;

  ResolutionInterfaceType get intType => commonElements.intType;
  ResolutionInterfaceType get doubleType => commonElements.doubleType;
  ResolutionInterfaceType get boolType => commonElements.boolType;
  ResolutionInterfaceType get stringType => commonElements.stringType;

  ResolutionDartType thisType;
  ResolutionDartType superType;

  Link<ResolutionDartType> cascadeTypes = const Link<ResolutionDartType>();

  bool analyzingInitializer = false;

  Map<Node, List<TypePromotion>> shownTypePromotionsMap =
      new Map<Node, List<TypePromotion>>();

  Map<VariableElement, Link<TypePromotion>> typePromotionsMap =
      new Map<VariableElement, Link<TypePromotion>>();

  Set<TypePromotion> reportedTypePromotions = new Set<TypePromotion>();

  void showTypePromotion(Node node, TypePromotion typePromotion) {
    List<TypePromotion> shownTypePromotions =
        shownTypePromotionsMap.putIfAbsent(node, () => <TypePromotion>[]);
    shownTypePromotions.add(typePromotion);
  }

  void registerKnownTypePromotion(TypePromotion typePromotion) {
    VariableElement variable = typePromotion.variable;
    Link<TypePromotion> knownTypes = typePromotionsMap.putIfAbsent(
        variable, () => const Link<TypePromotion>());
    typePromotionsMap[variable] = knownTypes.prepend(typePromotion);
  }

  void unregisterKnownTypePromotion(TypePromotion typePromotion) {
    VariableElement variable = typePromotion.variable;
    Link<TypePromotion> knownTypes = typePromotionsMap[variable].tail;
    if (knownTypes.isEmpty) {
      typePromotionsMap.remove(variable);
    } else {
      typePromotionsMap[variable] = knownTypes;
    }
  }

  List<TypePromotion> getShownTypePromotionsFor(Node node) {
    List<TypePromotion> shownTypePromotions = shownTypePromotionsMap[node];
    return shownTypePromotions != null ? shownTypePromotions : const [];
  }

  TypePromotion getKnownTypePromotion(VariableElement element) {
    Link<TypePromotion> promotions = typePromotionsMap[element];
    if (promotions != null) {
      while (!promotions.isEmpty) {
        TypePromotion typePromotion = promotions.head;
        if (typePromotion.isValid) {
          return typePromotion;
        }
        promotions = promotions.tail;
      }
    }
    return null;
  }

  ResolutionDartType getKnownType(VariableElement element) {
    TypePromotion typePromotion = getKnownTypePromotion(element);
    if (typePromotion != null) return typePromotion.type;
    return element.type;
  }

  TypeCheckerVisitor(this.compiler, TreeElements elements, this.types)
      : this.elements = elements,
        this.executableContext = elements.analyzedElement,
        this.currentClass = elements.analyzedElement != null
            ? elements.analyzedElement.enclosingClass
            : null {
    if (currentClass != null) {
      thisType = currentClass.thisType;
      superType = currentClass.supertype;
    } else {
      // If these are used, an error should have been reported by the resolver.
      thisType = const ResolutionDynamicType();
      superType = const ResolutionDynamicType();
    }
  }

  LibraryElement get currentLibrary => elements.analyzedElement.library;

  reportTypeWarning(Spannable spannable, MessageKind kind,
      [Map arguments = const {}]) {
    reporter.reportWarningMessage(spannable, kind, arguments);
  }

  reportMessage(Spannable spannable, MessageKind kind, Map arguments,
      {bool isHint: false}) {
    if (isHint) {
      reporter.reportHintMessage(spannable, kind, arguments);
    } else {
      reporter.reportWarningMessage(spannable, kind, arguments);
    }
  }

  reportTypePromotionHint(TypePromotion typePromotion) {
    if (!reportedTypePromotions.contains(typePromotion)) {
      reportedTypePromotions.add(typePromotion);
      for (TypePromotionMessage message in typePromotion.messages) {
        reporter.reportHint(message.hint, message.infos);
      }
    }
  }

  // TODO(karlklose): remove these functions.
  ResolutionDartType unhandledExpression() => const ResolutionDynamicType();

  ResolutionDartType analyzeNonVoid(Node node) {
    ResolutionDartType type = analyze(node);
    if (type.isVoid) {
      reportTypeWarning(node, MessageKind.VOID_EXPRESSION);
    }
    return type;
  }

  ResolutionDartType analyzeWithDefault(
      Node node, ResolutionDartType defaultValue) {
    return node != null ? analyze(node) : defaultValue;
  }

  /// If [inInitializer] is true, assignment should be interpreted as write to
  /// a field and not to a setter.
  ResolutionDartType analyze(Node node,
      {bool inInitializer: false, bool mustHaveType: true}) {
    if (node == null) {
      final String error = 'Unexpected node: null';
      if (lastSeenNode != null) {
        reporter.internalError(lastSeenNode, error);
      } else {
        reporter.internalError(executableContext, error);
      }
    } else {
      lastSeenNode = node;
    }
    bool previouslyInitializer = analyzingInitializer;
    analyzingInitializer = inInitializer;
    ResolutionDartType result = node.accept(this);
    analyzingInitializer = previouslyInitializer;
    if (result == null && mustHaveType) {
      reporter.internalError(node, 'Type is null.');
    }
    return result;
  }

  void analyzeUntyped(Node node, {bool inInitializer: false}) {
    if (node != null) {
      analyze(node, inInitializer: inInitializer, mustHaveType: false);
    }
  }

  void checkTypePromotion(Node node, TypePromotion typePromotion,
      {bool checkAccesses: false}) {
    VariableElement variable = typePromotion.variable;
    String variableName = variable.name;
    List<Node> potentialMutationsIn =
        elements.getPotentialMutationsIn(node, variable);
    if (!potentialMutationsIn.isEmpty) {
      DiagnosticMessage hint = reporter.createMessage(
          typePromotion.node,
          MessageKind.POTENTIAL_MUTATION,
          {'variableName': variableName, 'shownType': typePromotion.type});
      List<DiagnosticMessage> infos = <DiagnosticMessage>[];
      for (Node mutation in potentialMutationsIn) {
        infos.add(reporter.createMessage(
            mutation,
            MessageKind.POTENTIAL_MUTATION_HERE,
            {'variableName': variableName}));
      }
      typePromotion.addHint(hint, infos);
    }
    List<Node> potentialMutationsInClosures =
        elements.getPotentialMutationsInClosure(variable);
    if (!potentialMutationsInClosures.isEmpty) {
      DiagnosticMessage hint = reporter.createMessage(
          typePromotion.node,
          MessageKind.POTENTIAL_MUTATION_IN_CLOSURE,
          {'variableName': variableName, 'shownType': typePromotion.type});
      List<DiagnosticMessage> infos = <DiagnosticMessage>[];
      for (Node mutation in potentialMutationsInClosures) {
        infos.add(reporter.createMessage(
            mutation,
            MessageKind.POTENTIAL_MUTATION_IN_CLOSURE_HERE,
            {'variableName': variableName}));
      }
      typePromotion.addHint(hint, infos);
    }
    if (checkAccesses) {
      List<Node> accesses = elements.getAccessesByClosureIn(node, variable);
      List<Node> mutations = elements.getPotentialMutations(variable);
      if (!accesses.isEmpty && !mutations.isEmpty) {
        DiagnosticMessage hint = reporter.createMessage(
            typePromotion.node,
            MessageKind.ACCESSED_IN_CLOSURE,
            {'variableName': variableName, 'shownType': typePromotion.type});
        List<DiagnosticMessage> infos = <DiagnosticMessage>[];
        for (Node access in accesses) {
          infos.add(reporter.createMessage(
              access,
              MessageKind.ACCESSED_IN_CLOSURE_HERE,
              {'variableName': variableName}));
        }
        for (Node mutation in mutations) {
          infos.add(reporter.createMessage(
              mutation,
              MessageKind.POTENTIAL_MUTATION_HERE,
              {'variableName': variableName}));
        }
        typePromotion.addHint(hint, infos);
      }
    }
  }

  /// Show type promotions from [left] and [right] in [node] given that the
  /// promoted variables are not potentially mutated in [right].
  void reshowTypePromotions(Node node, Node left, Node right) {
    for (TypePromotion typePromotion in getShownTypePromotionsFor(left)) {
      typePromotion = typePromotion.copy();
      checkTypePromotion(right, typePromotion);
      showTypePromotion(node, typePromotion);
    }

    for (TypePromotion typePromotion in getShownTypePromotionsFor(right)) {
      typePromotion = typePromotion.copy();
      checkTypePromotion(right, typePromotion);
      showTypePromotion(node, typePromotion);
    }
  }

  /// Analyze [node] in the context of the known types shown in [context].
  ResolutionDartType analyzeInPromotedContext(Node context, Node node,
      {bool mustHaveType: true}) {
    Link<TypePromotion> knownForNode = const Link<TypePromotion>();
    for (TypePromotion typePromotion in getShownTypePromotionsFor(context)) {
      typePromotion = typePromotion.copy();
      checkTypePromotion(node, typePromotion, checkAccesses: true);
      knownForNode = knownForNode.prepend(typePromotion);
      registerKnownTypePromotion(typePromotion);
    }

    final ResolutionDartType type = analyze(node, mustHaveType: mustHaveType);

    while (!knownForNode.isEmpty) {
      unregisterKnownTypePromotion(knownForNode.head);
      knownForNode = knownForNode.tail;
    }

    return type;
  }

  /**
   * Check if a value of type [from] can be assigned to a variable, parameter or
   * return value of type [to].  If `isConst == true`, an error is emitted in
   * checked mode, otherwise a warning is issued.
   */
  bool checkAssignable(
      Spannable spannable, ResolutionDartType from, ResolutionDartType to,
      {bool isConst: false}) {
    if (!types.isAssignable(from, to)) {
      if (compiler.options.enableTypeAssertions && isConst) {
        reporter.reportErrorMessage(spannable, MessageKind.NOT_ASSIGNABLE,
            {'fromType': from, 'toType': to});
      } else {
        reporter.reportWarningMessage(spannable, MessageKind.NOT_ASSIGNABLE,
            {'fromType': from, 'toType': to});
      }
      return false;
    }
    return true;
  }

  checkCondition(Expression condition) {
    checkAssignable(condition, analyze(condition), boolType);
  }

  void pushCascadeType(ResolutionDartType type) {
    cascadeTypes = cascadeTypes.prepend(type);
  }

  ResolutionDartType popCascadeType() {
    ResolutionDartType type = cascadeTypes.head;
    cascadeTypes = cascadeTypes.tail;
    return type;
  }

  visitAssert(Assert node) {
    analyze(node.condition);
    if (node.hasMessage) analyze(node.message);
  }

  visitBlock(Block node) {
    analyzeUntyped(node.statements);
  }

  ResolutionDartType visitCascade(Cascade node) {
    analyze(node.expression);
    return popCascadeType();
  }

  ResolutionDartType visitCascadeReceiver(CascadeReceiver node) {
    ResolutionDartType type = analyze(node.expression);
    pushCascadeType(type);
    return type;
  }

  visitDoWhile(DoWhile node) {
    analyzeUntyped(node.body);
    checkCondition(node.condition);
  }

  visitExpressionStatement(ExpressionStatement node) {
    Expression expression = node.expression;
    analyze(expression);
  }

  /** Dart Programming Language Specification: 11.5.1 For Loop */
  visitFor(For node) {
    if (node.initializer != null) {
      analyzeUntyped(node.initializer);
    }
    if (node.condition != null) {
      checkCondition(node.condition);
    }
    if (node.update != null) {
      analyzeUntyped(node.update);
    }
    analyzeUntyped(node.body);
  }

  visitFunctionDeclaration(FunctionDeclaration node) {
    analyze(node.function);
  }

  ResolutionDartType visitFunctionExpression(FunctionExpression node) {
    ResolutionDartType type;
    ResolutionDartType returnType;
    final FunctionElement element = elements.getFunctionDefinition(node);
    assert(
        element != null, failedAt(node, 'FunctionExpression with no element'));
    if (Elements.isUnresolved(element)) return const ResolutionDynamicType();
    if (element.isGenerativeConstructor) {
      type = const ResolutionDynamicType();
      returnType = const ResolutionVoidType();

      element.functionSignature.forEachParameter((FormalElement parameter) {
        if (parameter.isInitializingFormal) {
          InitializingFormalElement fieldParameter = parameter;
          checkAssignable(parameter, parameter.type,
              fieldParameter.fieldElement.computeType(resolution));
        }
      });
      if (node.initializers != null) {
        analyzeUntyped(node.initializers, inInitializer: true);
      }
    } else {
      ResolutionFunctionType functionType = element.computeType(resolution);
      returnType = functionType.returnType;
      type = functionType;
    }
    ExecutableElement previousExecutableContext = executableContext;
    ResolutionDartType previousReturnType = expectedReturnType;
    expectedReturnType = returnType;
    AsyncMarker previousAsyncMarker = currentAsyncMarker;

    executableContext = element;
    currentAsyncMarker = element.asyncMarker;
    analyzeUntyped(node.body);

    executableContext = previousExecutableContext;
    expectedReturnType = previousReturnType;
    currentAsyncMarker = previousAsyncMarker;
    return type;
  }

  ResolutionDartType visitIdentifier(Identifier node) {
    if (node.isThis()) {
      return thisType;
    } else if (node.isSuper()) {
      return superType;
    } else {
      TypedElement element = elements[node];
      assert(element != null, failedAt(node, 'Missing element for identifier'));
      assert(element.isVariable || element.isParameter || element.isField,
          failedAt(node, 'Unexpected context element ${element}'));
      return element.computeType(resolution);
    }
  }

  visitIf(If node) {
    Expression condition = node.condition.expression;
    Statement thenPart = node.thenPart;

    checkCondition(node.condition);
    analyzeInPromotedContext(condition, thenPart, mustHaveType: false);
    if (node.elsePart != null) {
      analyzeUntyped(node.elsePart);
    }
  }

  void checkPrivateAccess(Node node, Element element, String name) {
    if (name != null &&
        Name.isPrivateName(name) &&
        element.library != currentLibrary) {
      reportTypeWarning(node, MessageKind.PRIVATE_ACCESS,
          {'name': name, 'libraryName': element.library.name});
    }
  }

  ElementAccess lookupMember(Node node, ResolutionDartType receiverType,
      String name, MemberKind memberKind, Element receiverElement,
      {bool lookupClassMember: false, bool isHint: false}) {
    if (receiverType.treatAsDynamic) {
      return const DynamicAccess();
    }

    Name memberName = new Name(name, currentLibrary,
        isSetter: memberKind == MemberKind.SETTER);

    // Lookup the class or interface member [name] in [interface].
    MemberSignature lookupMemberSignature(
        Name name, ResolutionInterfaceType interface) {
      MembersCreator.computeClassMembersByName(
          resolution, interface.element, name.text);
      return lookupClassMember || analyzingInitializer
          ? interface.lookupClassMember(name)
          : interface.lookupInterfaceMember(name);
    }

    // Compute the access of [name] on [type]. This function takes the special
    // 'call' method into account.
    ElementAccess getAccess(Name name, ResolutionDartType unaliasedBound,
        ResolutionInterfaceType interface) {
      MemberSignature member = lookupMemberSignature(memberName, interface);
      if (member != null) {
        if (member is ErroneousMember) {
          return const DynamicAccess();
        } else {
          return new MemberAccess(member);
        }
      }
      if (name == const PublicName('call')) {
        if (unaliasedBound.isFunctionType) {
          // This is an access the implicit 'call' method of a function type.
          return new FunctionCallAccess(receiverElement, unaliasedBound);
        }
        ResolutionInterfaceType functionType = commonElements.functionType;
        if (types.isSubtype(interface, functionType)) {
          // This is an access of the special 'call' method implicitly defined
          // on 'Function'. This method can be called with any arguments, which
          // we ensure by giving it the type 'dynamic'.
          return new FunctionCallAccess(null, const ResolutionDynamicType());
        }
      }
      return null;
    }

    ResolutionDartType unaliasedBound =
        Types.computeUnaliasedBound(resolution, receiverType);
    if (unaliasedBound.treatAsDynamic) {
      return new DynamicAccess();
    }
    ResolutionInterfaceType interface =
        Types.computeInterfaceType(resolution, unaliasedBound);
    ElementAccess access = getAccess(memberName, unaliasedBound, interface);
    if (access != null) {
      return access;
    }
    if (receiverElement != null &&
        (receiverElement.isVariable || receiverElement.isParameter)) {
      Link<TypePromotion> typePromotions = typePromotionsMap[receiverElement];
      if (typePromotions != null) {
        while (!typePromotions.isEmpty) {
          TypePromotion typePromotion = typePromotions.head;
          if (!typePromotion.isValid) {
            ResolutionDartType unaliasedBound =
                Types.computeUnaliasedBound(resolution, typePromotion.type);
            if (!unaliasedBound.treatAsDynamic) {
              ResolutionInterfaceType interface =
                  Types.computeInterfaceType(resolution, unaliasedBound);
              if (getAccess(memberName, unaliasedBound, interface) != null) {
                reportTypePromotionHint(typePromotion);
              }
            }
          }
          typePromotions = typePromotions.tail;
        }
      }
    }
    // We didn't find a member with the correct name.  If this lookup is for a
    // super or redirecting initializer, the resolver has already emitted an
    // error message.  If the target is a proxy, no warning needs to be emitted.
    // Otherwise, try to emit the most precise warning.
    if (!interface.element.isProxy && !analyzingInitializer) {
      bool foundPrivateMember = false;
      if (memberName.isPrivate) {
        void findPrivateMember(MemberSignature member) {
          if (memberName.isSimilarTo(member.name)) {
            PrivateName privateName = member.name;
            LibraryElement library = privateName.library;
            reportMessage(node, MessageKind.PRIVATE_ACCESS,
                {'name': name, 'libraryName': library.name},
                isHint: isHint);
            foundPrivateMember = true;
          }
        }

        // TODO(johnniwinther): Avoid computation of all class members.
        MembersCreator.computeAllClassMembers(resolution, interface.element);
        if (lookupClassMember) {
          interface.element.forEachClassMember(findPrivateMember);
        } else {
          interface.element.forEachInterfaceMember(findPrivateMember);
        }
      }
      if (!foundPrivateMember) {
        switch (memberKind) {
          case MemberKind.METHOD:
            reportMessage(node, MessageKind.UNDEFINED_METHOD,
                {'className': receiverType.name, 'memberName': name},
                isHint: isHint);
            break;
          case MemberKind.OPERATOR:
            reportMessage(node, MessageKind.UNDEFINED_OPERATOR,
                {'className': receiverType.name, 'memberName': name},
                isHint: isHint);
            break;
          case MemberKind.GETTER:
            if (lookupMemberSignature(memberName.setter, interface) != null) {
              // A setter is present so warn explicitly about the missing
              // getter.
              reportMessage(
                  node,
                  MessageKind.UNDEFINED_INSTANCE_GETTER_BUT_SETTER,
                  {'className': receiverType.name, 'memberName': name},
                  isHint: isHint);
            } else if (name == 'await') {
              Map arguments = {'className': receiverType.name};
              String functionName = executableContext.name;
              MessageKind kind;
              if (functionName == '') {
                kind = MessageKind.AWAIT_MEMBER_NOT_FOUND_IN_CLOSURE;
              } else {
                kind = MessageKind.AWAIT_MEMBER_NOT_FOUND;
                arguments['functionName'] = functionName;
              }
              reportMessage(node, kind, arguments, isHint: isHint);
            } else {
              reportMessage(node, MessageKind.UNDEFINED_GETTER,
                  {'className': receiverType.name, 'memberName': name},
                  isHint: isHint);
            }
            break;
          case MemberKind.SETTER:
            reportMessage(node, MessageKind.UNDEFINED_SETTER,
                {'className': receiverType.name, 'memberName': name},
                isHint: isHint);
            break;
        }
      }
    }
    return const DynamicAccess();
  }

  ResolutionDartType lookupMemberType(
      Node node, ResolutionDartType type, String name, MemberKind memberKind,
      {bool isHint: false}) {
    return lookupMember(node, type, name, memberKind, null, isHint: isHint)
        .computeType(resolution);
  }

  void analyzeArguments(Send send, Element element, ResolutionDartType type,
      [LinkBuilder<ResolutionDartType> argumentTypes]) {
    Link<Node> arguments = send.arguments;
    type.computeUnaliased(resolution);
    ResolutionDartType unaliasedType = type.unaliased;
    if (identical(unaliasedType.kind, ResolutionTypeKind.FUNCTION)) {
      /// Report [warning] including info(s) about the declaration of [element]
      /// or [type].
      void reportWarning(DiagnosticMessage warning) {
        // TODO(johnniwinther): Support pointing to individual parameters on
        // assignability warnings.
        List<DiagnosticMessage> infos = <DiagnosticMessage>[];
        Element declaration = element;
        if (declaration == null) {
          declaration = type.element;
        } else if (type.isTypedef) {
          infos.add(reporter.createMessage(declaration,
              MessageKind.THIS_IS_THE_DECLARATION, {'name': element.name}));
          declaration = type.element;
        }
        if (declaration != null) {
          infos.add(reporter.createMessage(
              declaration, MessageKind.THIS_IS_THE_METHOD));
        }
        reporter.reportWarning(warning, infos);
      }

      /// Report a warning on [node] if [argumentType] is not assignable to
      /// [parameterType].
      void checkAssignable(Spannable node, ResolutionDartType argumentType,
          ResolutionDartType parameterType) {
        if (!types.isAssignable(argumentType, parameterType)) {
          reportWarning(reporter.createMessage(node, MessageKind.NOT_ASSIGNABLE,
              {'fromType': argumentType, 'toType': parameterType}));
        }
      }

      ResolutionFunctionType funType = unaliasedType;
      Iterator<ResolutionDartType> parameterTypes =
          funType.parameterTypes.iterator;
      Iterator<ResolutionDartType> optionalParameterTypes =
          funType.optionalParameterTypes.iterator;
      while (!arguments.isEmpty) {
        Node argument = arguments.head;
        NamedArgument namedArgument = argument.asNamedArgument();
        if (namedArgument != null) {
          argument = namedArgument.expression;
          String argumentName = namedArgument.name.source;
          ResolutionDartType namedParameterType =
              funType.getNamedParameterType(argumentName);
          if (namedParameterType == null) {
            // TODO(johnniwinther): Provide better information on the called
            // function.
            reportWarning(reporter.createMessage(
                argument,
                MessageKind.NAMED_ARGUMENT_NOT_FOUND,
                {'argumentName': argumentName}));

            ResolutionDartType argumentType = analyze(argument);
            if (argumentTypes != null) argumentTypes.addLast(argumentType);
          } else {
            ResolutionDartType argumentType = analyze(argument);
            if (argumentTypes != null) argumentTypes.addLast(argumentType);
            checkAssignable(argument, argumentType, namedParameterType);
          }
        } else {
          if (!parameterTypes.moveNext()) {
            if (!optionalParameterTypes.moveNext()) {
              // TODO(johnniwinther): Provide better information on the
              // called function.
              reportWarning(reporter.createMessage(
                  argument, MessageKind.ADDITIONAL_ARGUMENT));

              ResolutionDartType argumentType = analyze(argument);
              if (argumentTypes != null) argumentTypes.addLast(argumentType);
            } else {
              ResolutionDartType argumentType = analyze(argument);
              if (argumentTypes != null) argumentTypes.addLast(argumentType);
              checkAssignable(
                  argument, argumentType, optionalParameterTypes.current);
            }
          } else {
            ResolutionDartType argumentType = analyze(argument);
            if (argumentTypes != null) argumentTypes.addLast(argumentType);
            checkAssignable(argument, argumentType, parameterTypes.current);
          }
        }
        arguments = arguments.tail;
      }
      if (parameterTypes.moveNext()) {
        // TODO(johnniwinther): Provide better information on the called
        // function.
        reportWarning(reporter.createMessage(send, MessageKind.MISSING_ARGUMENT,
            {'argumentType': parameterTypes.current}));
      }
    } else {
      while (!arguments.isEmpty) {
        ResolutionDartType argumentType = analyze(arguments.head);
        if (argumentTypes != null) argumentTypes.addLast(argumentType);
        arguments = arguments.tail;
      }
    }
  }

  // Analyze the invocation [node] of [elementAccess].
  //
  // If provided [argumentTypes] is filled with the argument types during
  // analysis.
  ResolutionDartType analyzeInvocation(Send node, ElementAccess elementAccess,
      [LinkBuilder<ResolutionDartType> argumentTypes]) {
    ResolutionDartType type = elementAccess.computeType(resolution);
    if (elementAccess.isCallable(compiler)) {
      analyzeArguments(node, elementAccess.element, type, argumentTypes);
    } else {
      reportTypeWarning(
          node, MessageKind.NOT_CALLABLE, {'elementName': elementAccess.name});
      analyzeArguments(node, elementAccess.element,
          const ResolutionDynamicType(), argumentTypes);
    }
    type.computeUnaliased(resolution);
    type = type.unaliased;
    if (type.isFunctionType) {
      ResolutionFunctionType funType = type;
      return funType.returnType;
    } else {
      return const ResolutionDynamicType();
    }
  }

  /**
   * Computes the [ElementAccess] for [name] on the [node] possibly using the
   * [element] provided for [node] by the resolver.
   */
  ElementAccess computeAccess(
      Send node, String name, Element element, MemberKind memberKind,
      {bool lookupClassMember: false}) {
    if (Elements.isMalformed(element)) {
      return const DynamicAccess();
    }
    if (node.receiver != null) {
      Element receiverElement = elements[node.receiver];
      if (receiverElement != null) {
        if (receiverElement.isPrefix) {
          if (node.isConditional) {
            // Skip cases like `prefix?.topLevel`.
            return const DynamicAccess();
          }
          assert(
              element != null, failedAt(node, 'Prefixed node has no element.'));
          return computeResolvedAccess(node, name, element, memberKind);
        }
      }
      // e.foo() for some expression e.
      ResolutionDartType receiverType = analyze(node.receiver);
      if (receiverType.treatAsDynamic || receiverType.isVoid) {
        return const DynamicAccess();
      }
      return lookupMember(
          node, receiverType, name, memberKind, elements[node.receiver],
          lookupClassMember:
              lookupClassMember || element != null && element.isStatic);
    } else {
      return computeResolvedAccess(node, name, element, memberKind);
    }
  }

  /**
   * Computes the [ElementAccess] for [name] on the [node] using the [element]
   * provided for [node] by the resolver.
   */
  ElementAccess computeResolvedAccess(
      Send node, String name, Element element, MemberKind memberKind) {
    if (element == null) {
      // foo() where foo is unresolved.
      return lookupMember(node, thisType, name, memberKind, null);
    } else if (element.isMalformed) {
      // foo() where foo is erroneous.
      return const DynamicAccess();
    } else if (element.impliesType) {
      // The literal `Foo` where Foo is a class, a typedef, or a type variable.
      if (elements.isTypeLiteral(node)) {
        return new TypeLiteralAccess(elements.getTypeLiteralType(node));
      }
      return createResolvedAccess(node, name, element);
    } else if (element.isClassMember) {
      // foo() where foo is a member.
      return lookupMember(node, thisType, name, memberKind, null,
          lookupClassMember: element.isStatic);
    } else if (element.isFunction) {
      // foo() where foo is a method in the same class.
      return createResolvedAccess(node, name, element);
    } else if (element.isVariable ||
        element.isRegularParameter ||
        element.isField ||
        element.isInitializingFormal) {
      // foo() where foo is a field in the same class.
      return createResolvedAccess(node, name, element);
    } else if (element.isGetter || element.isSetter) {
      return createResolvedAccess(node, name, element);
    } else {
      reporter.internalError(
          element, 'Unexpected element kind ${element.kind}.');
      return null;
    }
  }

  ElementAccess createResolvedAccess(Send node, String name, Element element) {
    checkPrivateAccess(node, element, name);
    return createPromotedAccess(element);
  }

  ElementAccess createPromotedAccess(Element element) {
    if (element.isVariable || element.isParameter) {
      TypePromotion typePromotion = getKnownTypePromotion(element);
      if (typePromotion != null) {
        return new PromotedAccess(element, typePromotion.type);
      }
    }
    return new ResolvedAccess(element);
  }

  /**
   * Computes the type of the access of [name] on the [node] possibly using the
   * [element] provided for [node] by the resolver.
   */
  ResolutionDartType computeAccessType(
      Send node, String name, Element element, MemberKind memberKind,
      {bool lookupClassMember: false}) {
    ResolutionDartType type = computeAccess(node, name, element, memberKind,
            lookupClassMember: lookupClassMember)
        .computeType(resolution);
    if (type == null) {
      reporter.internalError(node, 'Type is null on access of $name on $node.');
    }
    return type;
  }

  /// Compute a version of [shownType] that is more specific that [knownType].
  /// This is used to provided better hints when trying to promote a supertype
  /// to a raw subtype. For instance trying to promote `Iterable<int>` to `List`
  /// we suggest the use of `List<int>`, which would make promotion valid.
  ResolutionDartType computeMoreSpecificType(
      ResolutionDartType shownType, ResolutionDartType knownType) {
    if (knownType.isInterfaceType &&
        shownType.isInterfaceType &&
        types.isSubtype(shownType.asRaw(), knownType)) {
      // For the comments in the block, assume the hierarchy:
      //     class A<T, V> {}
      //     class B<S, U> extends A<S, int> {}
      // and a promotion from a [knownType] of `A<double, int>` to a
      // [shownType] of `B`.
      ResolutionInterfaceType knownInterfaceType = knownType;
      ClassElement shownClass = shownType.element;

      // Compute `B<double, dynamic>` as the subtype of `A<double, int>` using
      // the relation between `A<S, int>` and `A<double, int>`.
      MoreSpecificSubtypeVisitor visitor =
          new MoreSpecificSubtypeVisitor(types);
      ResolutionInterfaceType shownTypeGeneric =
          visitor.computeMoreSpecific(shownClass, knownInterfaceType);

      if (shownTypeGeneric != null &&
          types.isMoreSpecific(shownTypeGeneric, knownType)) {
        // This should be the case but we double-check.
        // TODO(johnniwinther): Ensure that we don't suggest malbounded types.
        return shownTypeGeneric;
      }
    }
    return null;
  }

  ResolutionDartType visitSend(Send node) {
    Element element = elements[node];

    if (element != null && element.isConstructor) {
      ResolutionDartType receiverType;
      if (node.receiver != null) {
        receiverType = analyze(node.receiver);
      } else if (node.selector.isSuper()) {
        // TODO(johnniwinther): Lookup super-member in class members.
        receiverType = superType;
      } else {
        assert(node.selector.isThis());
        receiverType = thisType;
      }
      ResolutionDartType constructorType =
          computeConstructorType(element, receiverType);
      analyzeArguments(node, element, constructorType);
      return const ResolutionDynamicType();
    }

    Identifier selector = node.selector.asIdentifier();
    if (Elements.isClosureSend(node, element)) {
      if (element != null) {
        if (element.isError) {
          // foo() where foo is erroneous
          return analyzeInvocation(node, const DynamicAccess());
        } else {
          assert(element.isLocal,
              failedAt(node, "Unexpected element $element in closure send."));
          // foo() where foo is a local or a parameter.
          return analyzeInvocation(node, createPromotedAccess(element));
        }
      } else {
        // exp() where exp is some complex expression like (o) or foo().
        ResolutionDartType type = analyze(node.selector);
        return analyzeInvocation(node, new TypeAccess(type));
      }
    } else if (Elements.isMalformed(element) && selector == null) {
      // exp() where exp is an erroneous construct like `new Unresolved()`.
      ResolutionDartType type = analyze(node.selector);
      return analyzeInvocation(node, new TypeAccess(type));
    }

    String name = selector.source;

    if (node.isOperator && identical(name, 'is')) {
      analyze(node.receiver);
      if (!node.isIsNotCheck) {
        Element variable = elements[node.receiver];
        if (variable == null) {
          // Look for the variable element within parenthesized expressions.
          ParenthesizedExpression parentheses =
              node.receiver.asParenthesizedExpression();
          while (parentheses != null) {
            variable = elements[parentheses.expression];
            if (variable != null) break;
            parentheses = parentheses.expression.asParenthesizedExpression();
          }
        }

        if (variable != null && (variable.isVariable || variable.isParameter)) {
          ResolutionDartType knownType = getKnownType(variable);
          if (!knownType.isDynamic) {
            ResolutionDartType shownType =
                elements.getType(node.arguments.head);
            TypePromotion typePromotion =
                new TypePromotion(node, variable, shownType);
            if (!types.isMoreSpecific(shownType, knownType)) {
              String variableName = variable.name;
              if (!types.isSubtype(shownType, knownType)) {
                typePromotion.addHint(reporter.createMessage(
                    node, MessageKind.NOT_MORE_SPECIFIC_SUBTYPE, {
                  'variableName': variableName,
                  'shownType': shownType,
                  'knownType': knownType
                }));
              } else {
                ResolutionDartType shownTypeSuggestion =
                    computeMoreSpecificType(shownType, knownType);
                if (shownTypeSuggestion != null) {
                  typePromotion.addHint(reporter.createMessage(
                      node, MessageKind.NOT_MORE_SPECIFIC_SUGGESTION, {
                    'variableName': variableName,
                    'shownType': shownType,
                    'shownTypeSuggestion': shownTypeSuggestion,
                    'knownType': knownType
                  }));
                } else {
                  typePromotion.addHint(reporter.createMessage(
                      node, MessageKind.NOT_MORE_SPECIFIC, {
                    'variableName': variableName,
                    'shownType': shownType,
                    'knownType': knownType
                  }));
                }
              }
            }
            showTypePromotion(node, typePromotion);
          }
        }
      }
      return boolType;
    }
    if (node.isOperator && identical(name, 'as')) {
      analyze(node.receiver);
      return elements.getType(node.arguments.head);
    } else if (node.isOperator) {
      final Node receiver = node.receiver;
      final ResolutionDartType receiverType = analyze(receiver);
      if (identical(name, '==') ||
          identical(name, '!=')
          // TODO(johnniwinther): Remove these.
          ||
          identical(name, '===') ||
          identical(name, '!==')) {
        // Analyze argument.
        analyze(node.arguments.head);
        return boolType;
      } else if (identical(name, '||')) {
        checkAssignable(receiver, receiverType, boolType);
        final Node argument = node.arguments.head;
        final ResolutionDartType argumentType = analyze(argument);
        checkAssignable(argument, argumentType, boolType);
        return boolType;
      } else if (identical(name, '&&')) {
        checkAssignable(receiver, receiverType, boolType);
        final Node argument = node.arguments.head;

        final ResolutionDartType argumentType =
            analyzeInPromotedContext(receiver, argument);

        reshowTypePromotions(node, receiver, argument);

        checkAssignable(argument, argumentType, boolType);
        return boolType;
      } else if (identical(name, '!')) {
        checkAssignable(receiver, receiverType, boolType);
        return boolType;
      } else if (identical(name, '?')) {
        return boolType;
      } else if (identical(name, '??')) {
        final Node argument = node.arguments.head;
        final ResolutionDartType argumentType = analyze(argument);
        return types.computeLeastUpperBound(receiverType, argumentType);
      }
      String operatorName = selector.source;
      if (identical(name, '-') && node.arguments.isEmpty) {
        operatorName = 'unary-';
      }
      assert(
          identical(name, '+') ||
              identical(name, '=') ||
              identical(name, '-') ||
              identical(name, '*') ||
              identical(name, '/') ||
              identical(name, '%') ||
              identical(name, '~/') ||
              identical(name, '|') ||
              identical(name, '&') ||
              identical(name, '^') ||
              identical(name, '~') ||
              identical(name, '<<') ||
              identical(name, '>>') ||
              identical(name, '<') ||
              identical(name, '>') ||
              identical(name, '<=') ||
              identical(name, '>=') ||
              identical(name, '[]'),
          failedAt(node, 'Unexpected operator $name'));

      // TODO(karlklose): handle `void` in expression context by calling
      // [analyzeNonVoid] instead of [analyze].
      ElementAccess access = receiverType.isVoid
          ? const DynamicAccess()
          : lookupMember(
              node, receiverType, operatorName, MemberKind.OPERATOR, null);
      LinkBuilder<ResolutionDartType> argumentTypesBuilder =
          new LinkBuilder<ResolutionDartType>();
      ResolutionDartType resultType =
          analyzeInvocation(node, access, argumentTypesBuilder);
      if (receiverType == intType) {
        if (identical(name, '+') ||
            identical(operatorName, '-') ||
            identical(name, '*') ||
            identical(name, '%')) {
          ResolutionDartType argumentType = argumentTypesBuilder.toLink().head;
          if (argumentType == intType) {
            return intType;
          } else if (argumentType == doubleType) {
            return doubleType;
          }
        }
      }
      return resultType;
    } else if (node.isPropertyAccess) {
      ElementAccess access =
          computeAccess(node, selector.source, element, MemberKind.GETTER);
      return access.computeType(resolution);
    } else if (node.isFunctionObjectInvocation) {
      return unhandledExpression();
    } else {
      ElementAccess access =
          computeAccess(node, selector.source, element, MemberKind.METHOD);
      return analyzeInvocation(node, access);
    }
  }

  /// Returns the first type in the list or [:dynamic:] if the list is empty.
  ResolutionDartType firstType(List<ResolutionDartType> list) {
    return list.isEmpty ? const ResolutionDynamicType() : list.first;
  }

  /**
   * Returns the second type in the list or [:dynamic:] if the list is too
   * short.
   */
  ResolutionDartType secondType(List<ResolutionDartType> list) {
    return list.length < 2 ? const ResolutionDynamicType() : list[1];
  }

  /**
   * Checks [: target o= value :] for some operator o, and returns the type
   * of the result. This method also handles increment/decrement expressions
   * like [: target++ :].
   */
  ResolutionDartType checkAssignmentOperator(SendSet node, String operatorName,
      Node valueNode, ResolutionDartType value) {
    assert(!node.isIndex, failedAt(node));
    Element setterElement = elements[node];
    Element getterElement = elements[node.selector];
    Identifier selector = node.selector;
    ResolutionDartType getter = computeAccessType(
        node, selector.source, getterElement, MemberKind.GETTER);
    ResolutionDartType setter = computeAccessType(
        node, selector.source, setterElement, MemberKind.SETTER);
    // [operator] is the type of operator+ or operator- on [target].
    ResolutionDartType operator =
        lookupMemberType(node, getter, operatorName, MemberKind.OPERATOR);
    if (operator is ResolutionFunctionType) {
      ResolutionFunctionType operatorType = operator;
      // [result] is the type of target o value.
      ResolutionDartType result = operatorType.returnType;
      ResolutionDartType operatorArgument =
          firstType(operatorType.parameterTypes);
      // Check target o value.
      bool validValue = checkAssignable(valueNode, value, operatorArgument);
      if (validValue || !(node.isPrefix || node.isPostfix)) {
        // Check target = result.
        checkAssignable(node.assignmentOperator, result, setter);
      }
      return node.isPostfix ? getter : result;
    }
    return const ResolutionDynamicType();
  }

  /**
   * Checks [: base[key] o= value :] for some operator o, and returns the type
   * of the result. This method also handles increment/decrement expressions
   * like [: base[key]++ :].
   */
  ResolutionDartType checkIndexAssignmentOperator(SendSet node,
      String operatorName, Node valueNode, ResolutionDartType value) {
    assert(node.isIndex, failedAt(node));
    final ResolutionDartType base = analyze(node.receiver);
    final Node keyNode = node.arguments.head;
    final ResolutionDartType key = analyze(keyNode);

    // [indexGet] is the type of operator[] on [base].
    ResolutionDartType indexGet =
        lookupMemberType(node, base, '[]', MemberKind.OPERATOR);
    if (indexGet is ResolutionFunctionType) {
      ResolutionFunctionType indexGetType = indexGet;
      ResolutionDartType indexGetKey = firstType(indexGetType.parameterTypes);
      // Check base[key].
      bool validKey = checkAssignable(keyNode, key, indexGetKey);

      // [element] is the type of base[key].
      ResolutionDartType element = indexGetType.returnType;
      // [operator] is the type of operator o on [element].
      ResolutionDartType operator =
          lookupMemberType(node, element, operatorName, MemberKind.OPERATOR);
      if (operator is ResolutionFunctionType) {
        ResolutionFunctionType operatorType = operator;

        // Check base[key] o value.
        ResolutionDartType operatorArgument =
            firstType(operatorType.parameterTypes);
        bool validValue = checkAssignable(valueNode, value, operatorArgument);

        // [result] is the type of base[key] o value.
        ResolutionDartType result = operatorType.returnType;

        // [indexSet] is the type of operator[]= on [base].
        ResolutionDartType indexSet =
            lookupMemberType(node, base, '[]=', MemberKind.OPERATOR);
        if (indexSet is ResolutionFunctionType) {
          ResolutionFunctionType indexSetType = indexSet;
          ResolutionDartType indexSetKey =
              firstType(indexSetType.parameterTypes);
          ResolutionDartType indexSetValue =
              secondType(indexSetType.parameterTypes);

          if (validKey || indexGetKey != indexSetKey) {
            // Only check base[key] on []= if base[key] was valid for [] or
            // if the key types differ.
            checkAssignable(keyNode, key, indexSetKey);
          }
          // Check base[key] = result
          if (validValue || !(node.isPrefix || node.isPostfix)) {
            checkAssignable(node.assignmentOperator, result, indexSetValue);
          }
        }
        return node.isPostfix ? element : result;
      }
    }
    return const ResolutionDynamicType();
  }

  visitSendSet(SendSet node) {
    Element element = elements[node];
    Identifier selector = node.selector;
    final name = node.assignmentOperator.source;
    if (identical(name, '=') || identical(name, '??=')) {
      // e1 = value
      if (node.isIndex) {
        // base[key] = value
        final ResolutionDartType base = analyze(node.receiver);
        final Node keyNode = node.arguments.head;
        final ResolutionDartType key = analyze(keyNode);
        final Node valueNode = node.arguments.tail.head;
        final ResolutionDartType value = analyze(valueNode);
        ResolutionDartType indexSet =
            lookupMemberType(node, base, '[]=', MemberKind.OPERATOR);
        ResolutionDartType indexSetValue = const ResolutionDynamicType();
        if (indexSet is ResolutionFunctionType) {
          ResolutionFunctionType indexSetType = indexSet;
          ResolutionDartType indexSetKey =
              firstType(indexSetType.parameterTypes);
          checkAssignable(keyNode, key, indexSetKey);
          indexSetValue = secondType(indexSetType.parameterTypes);
          checkAssignable(node.assignmentOperator, value, indexSetValue);
        }
        return identical(name, '=')
            ? value
            : types.computeLeastUpperBound(value, indexSetValue);
      } else {
        // target = value
        ResolutionDartType target;
        if (analyzingInitializer) {
          // Field declaration `Foo target = value;` or initializer
          // `this.target = value`. Lookup the getter `target` in the class
          // members.
          target = computeAccessType(
              node, selector.source, element, MemberKind.GETTER,
              lookupClassMember: true);
        } else {
          // Normal assignment `target = value`.
          target = computeAccessType(
              node, selector.source, element, MemberKind.SETTER);
        }
        final Node valueNode = node.arguments.head;
        final ResolutionDartType value = analyze(valueNode);
        checkAssignable(node.assignmentOperator, value, target);
        return identical(name, '=')
            ? value
            : types.computeLeastUpperBound(value, target);
      }
    } else if (identical(name, '++') || identical(name, '--')) {
      // e++ or e--
      String operatorName = identical(name, '++') ? '+' : '-';
      if (node.isIndex) {
        // base[key]++, base[key]--, ++base[key], or --base[key]
        return checkIndexAssignmentOperator(
            node, operatorName, node.assignmentOperator, intType);
      } else {
        // target++, target--, ++target, or --target
        return checkAssignmentOperator(
            node, operatorName, node.assignmentOperator, intType);
      }
    } else {
      // e1 o= e2 for some operator o.
      String operatorName;
      switch (name) {
        case '+=':
          operatorName = '+';
          break;
        case '-=':
          operatorName = '-';
          break;
        case '*=':
          operatorName = '*';
          break;
        case '/=':
          operatorName = '/';
          break;
        case '%=':
          operatorName = '%';
          break;
        case '~/=':
          operatorName = '~/';
          break;
        case '&=':
          operatorName = '&';
          break;
        case '|=':
          operatorName = '|';
          break;
        case '^=':
          operatorName = '^';
          break;
        case '<<=':
          operatorName = '<<';
          break;
        case '>>=':
          operatorName = '>>';
          break;
        default:
          reporter.internalError(node, 'Unexpected assignment operator $name.');
      }
      if (node.isIndex) {
        // base[key] o= value for some operator o.
        final Node valueNode = node.arguments.tail.head;
        final ResolutionDartType value = analyze(valueNode);
        return checkIndexAssignmentOperator(
            node, operatorName, valueNode, value);
      } else {
        // target o= value for some operator o.
        final Node valueNode = node.arguments.head;
        final ResolutionDartType value = analyze(valueNode);
        return checkAssignmentOperator(node, operatorName, valueNode, value);
      }
    }
  }

  ResolutionDartType visitLiteralInt(LiteralInt node) {
    return intType;
  }

  ResolutionDartType visitLiteralDouble(LiteralDouble node) {
    return doubleType;
  }

  ResolutionDartType visitLiteralBool(LiteralBool node) {
    return boolType;
  }

  ResolutionDartType visitLiteralString(LiteralString node) {
    return stringType;
  }

  ResolutionDartType visitStringJuxtaposition(StringJuxtaposition node) {
    analyze(node.first);
    analyze(node.second);
    return stringType;
  }

  ResolutionDartType visitLiteralNull(LiteralNull node) {
    return const ResolutionDynamicType();
  }

  ResolutionInterfaceType visitLiteralSymbol(LiteralSymbol node) {
    return commonElements.symbolType;
  }

  ResolutionDartType computeConstructorType(
      ConstructorElement constructor, ResolutionDartType type) {
    if (Elements.isUnresolved(constructor))
      return const ResolutionDynamicType();
    ResolutionDartType constructorType = constructor.computeType(resolution);
    if (identical(type.kind, ResolutionTypeKind.INTERFACE)) {
      if (constructor.isSynthesized) {
        // TODO(johnniwinther): Remove this when synthesized constructors handle
        // type variables correctly.
        ResolutionInterfaceType interfaceType = type;
        ClassElement receiverElement = interfaceType.element;
        while (receiverElement.isMixinApplication) {
          receiverElement = receiverElement.supertype.element;
        }
        constructorType = constructorType
            .substByContext(interfaceType.asInstanceOf(receiverElement));
      } else {
        constructorType = constructorType.substByContext(type);
      }
    }
    return constructorType;
  }

  ResolutionDartType visitNewExpression(NewExpression node) {
    Element element = elements[node.send];
    if (Elements.isUnresolved(element)) return const ResolutionDynamicType();

    checkPrivateAccess(node, element, element.name);

    ResolutionDartType newType = elements.getType(node);
    assert(newType != null,
        failedAt(node, "No new type registered in $elements."));
    ResolutionDartType constructorType =
        computeConstructorType(element, newType);
    analyzeArguments(node.send, element, constructorType);
    return newType;
  }

  ResolutionDartType visitLiteralList(LiteralList node) {
    ResolutionInterfaceType listType = elements.getType(node);
    ResolutionDartType listElementType = firstType(listType.typeArguments);
    for (Link<Node> link = node.elements.nodes;
        !link.isEmpty;
        link = link.tail) {
      Node element = link.head;
      ResolutionDartType elementType = analyze(element);
      checkAssignable(element, elementType, listElementType,
          isConst: node.isConst);
    }
    return listType;
  }

  visitNodeList(NodeList node) {
    for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) {
      analyzeUntyped(link.head, inInitializer: analyzingInitializer);
    }
  }

  visitRedirectingFactoryBody(RedirectingFactoryBody node) {
    // TODO(lrn): Typecheck the body. It must refer to the constructor
    // of a subtype.
  }

  visitRethrow(Rethrow node) {
    // Nothing to do here.
  }

  /** Dart Programming Language Specification: 11.10 Return */
  visitReturn(Return node) {
    if (identical(node.beginToken.stringValue, 'native')) {
      return null;
    }

    final Node expression = node.expression;

    // Executing a return statement return e; [...] It is a static type warning
    // if the type of e may not be assigned to the declared return type of the
    // immediately enclosing function.
    if (expression != null) {
      ResolutionDartType expressionType = analyze(expression);
      if (executableContext.isGenerativeConstructor) {
        // The resolver already emitted an error for this expression.
      } else {
        if (currentAsyncMarker == AsyncMarker.ASYNC) {
          ResolutionInterfaceType futureOfFlattenedType =
              commonElements.futureType(types.flatten(expressionType));
          expressionType = futureOfFlattenedType;
        }
        if (expectedReturnType.isVoid &&
            !types.isAssignable(expressionType, const ResolutionVoidType())) {
          // In `void f(...) => e`, `e` can have any type.
          if (!node.isArrowBody) {
            reportTypeWarning(expression, MessageKind.RETURN_VALUE_IN_VOID);
          }
        } else {
          checkAssignable(expression, expressionType, expectedReturnType);
        }
      }
    } else if (currentAsyncMarker != AsyncMarker.SYNC) {
      // `return;` is allowed.
    } else if (!types.isAssignable(
        expectedReturnType, const ResolutionVoidType())) {
      // Let f be the function immediately enclosing a return statement of the
      // form 'return;' It is a static warning if both of the following
      // conditions hold:
      // - f is not a generative constructor.
      // - The return type of f may not be assigned to void.
      reportTypeWarning(
          node, MessageKind.RETURN_NOTHING, {'returnType': expectedReturnType});
    }
  }

  ResolutionDartType visitThrow(Throw node) {
    // TODO(johnniwinther): Handle reachability.
    analyze(node.expression);
    return const ResolutionDynamicType();
  }

  ResolutionDartType visitAwait(Await node) {
    ResolutionDartType expressionType = analyze(node.expression);
    if (resolution.target.supportsAsyncAwait) {
      return types.flatten(expressionType);
    } else {
      return const ResolutionDynamicType();
    }
  }

  visitYield(Yield node) {
    ResolutionDartType resultType = analyze(node.expression);
    if (!node.hasStar) {
      if (currentAsyncMarker.isAsync) {
        ResolutionInterfaceType streamOfResultType =
            commonElements.streamType(resultType);
        resultType = streamOfResultType;
      } else {
        ResolutionInterfaceType iterableOfResultType =
            commonElements.iterableType(resultType);
        resultType = iterableOfResultType;
      }
    } else {
      if (currentAsyncMarker.isAsync) {
        // The static type of expression must be assignable to Stream.
        ResolutionInterfaceType streamType = commonElements.streamType();
        checkAssignable(node, resultType, streamType);
      } else {
        // The static type of expression must be assignable to Iterable.
        ResolutionInterfaceType iterableType = commonElements.iterableType();
        checkAssignable(node, resultType, iterableType);
      }
    }
    // The static type of the result must be assignable to the declared type.
    checkAssignable(node, resultType, expectedReturnType);
  }

  ResolutionDartType visitTypeAnnotation(TypeAnnotation node) {
    return elements.getType(node);
  }

  ResolutionDartType analyzeVariableTypeAnnotation(VariableDefinitions node) {
    ResolutionDartType type =
        analyzeWithDefault(node.type, const ResolutionDynamicType());
    if (type.isVoid) {
      reportTypeWarning(node.type, MessageKind.VOID_VARIABLE);
      type = const ResolutionDynamicType();
    }
    return type;
  }

  void analyzeVariableInitializer(
      Spannable spannable, ResolutionDartType declaredType, Node initializer) {
    if (initializer == null) return;

    ResolutionDartType expressionType = analyzeNonVoid(initializer);
    checkAssignable(spannable, expressionType, declaredType);
  }

  visitVariableDefinitions(VariableDefinitions node) {
    ResolutionDartType type = analyzeVariableTypeAnnotation(node);
    for (Link<Node> link = node.definitions.nodes;
        !link.isEmpty;
        link = link.tail) {
      Node definition = link.head;
      assert(definition is Identifier || definition is SendSet,
          failedAt(definition, 'expected identifier or initialization'));
      if (definition is SendSet) {
        SendSet initialization = definition;
        analyzeVariableInitializer(initialization.assignmentOperator, type,
            initialization.arguments.head);
        // TODO(sigmund): explore inferring a type for `var` using the RHS (like
        // DDC does), for example:
        // if (node.type == null && node.modifiers.isVar &&
        //     !initializer.isDynamic) {
        //   var variable = elements[definition];
        //   if (variable != null) {
        //     var typePromotion = new TypePromotion(
        //         node, variable, initializer);
        //     registerKnownTypePromotion(typePromotion);
        //   }
        // }
      }
    }
  }

  visitWhile(While node) {
    checkCondition(node.condition);
    analyzeUntyped(node.body);
  }

  ResolutionDartType visitParenthesizedExpression(
      ParenthesizedExpression node) {
    Expression expression = node.expression;
    ResolutionDartType type = analyze(expression);
    for (TypePromotion typePromotion in getShownTypePromotionsFor(expression)) {
      showTypePromotion(node, typePromotion);
    }
    return type;
  }

  ResolutionDartType visitConditional(Conditional node) {
    Expression condition = node.condition;
    Expression thenExpression = node.thenExpression;

    checkCondition(condition);

    ResolutionDartType thenType =
        analyzeInPromotedContext(condition, thenExpression);

    ResolutionDartType elseType = analyze(node.elseExpression);
    return types.computeLeastUpperBound(thenType, elseType);
  }

  visitStringInterpolation(StringInterpolation node) {
    node.visitChildren(this);
    return stringType;
  }

  visitStringInterpolationPart(StringInterpolationPart node) {
    node.visitChildren(this);
    return stringType;
  }

  visitEmptyStatement(EmptyStatement node) {
    // Nothing to do here.
  }

  visitBreakStatement(BreakStatement node) {
    // Nothing to do here.
  }

  visitContinueStatement(ContinueStatement node) {
    // Nothing to do here.
  }

  ResolutionDartType computeForInElementType(ForIn node) {
    VariableDefinitions declaredIdentifier =
        node.declaredIdentifier.asVariableDefinitions();
    if (declaredIdentifier != null) {
      return analyzeWithDefault(
          declaredIdentifier.type, const ResolutionDynamicType());
    } else {
      return analyze(node.declaredIdentifier);
    }
  }

  visitAsyncForIn(AsyncForIn node) {
    ResolutionDartType elementType = computeForInElementType(node);
    ResolutionDartType expressionType = analyze(node.expression);
    if (resolution.target.supportsAsyncAwait) {
      ResolutionInterfaceType streamOfDynamic = commonElements.streamType();
      if (!types.isAssignable(expressionType, streamOfDynamic)) {
        reportMessage(node.expression, MessageKind.NOT_ASSIGNABLE,
            {'fromType': expressionType, 'toType': streamOfDynamic},
            isHint: true);
      } else {
        ResolutionInterfaceType interfaceType =
            Types.computeInterfaceType(resolution, expressionType);
        if (interfaceType != null) {
          ResolutionInterfaceType streamType =
              interfaceType.asInstanceOf(streamOfDynamic.element);
          if (streamType != null) {
            ResolutionDartType streamElementType =
                streamType.typeArguments.first;
            if (!types.isAssignable(streamElementType, elementType)) {
              reportMessage(
                  node.expression,
                  MessageKind.FORIN_NOT_ASSIGNABLE,
                  {
                    'currentType': streamElementType,
                    'expressionType': expressionType,
                    'elementType': elementType
                  },
                  isHint: true);
            }
          }
        }
      }
    }
    analyzeUntyped(node.body);
  }

  visitSyncForIn(SyncForIn node) {
    ResolutionDartType elementType = computeForInElementType(node);
    ResolutionDartType expressionType = analyze(node.expression);
    ResolutionDartType iteratorType = lookupMemberType(node.expression,
        expressionType, Identifiers.iterator, MemberKind.GETTER);
    ResolutionDartType currentType = lookupMemberType(
        node.expression, iteratorType, Identifiers.current, MemberKind.GETTER,
        isHint: true);
    if (!types.isAssignable(currentType, elementType)) {
      reportMessage(
          node.expression,
          MessageKind.FORIN_NOT_ASSIGNABLE,
          {
            'currentType': currentType,
            'expressionType': expressionType,
            'elementType': elementType
          },
          isHint: true);
    }
    analyzeUntyped(node.body);
  }

  visitLabeledStatement(LabeledStatement node) {
    analyzeUntyped(node.statement);
  }

  visitLiteralMap(LiteralMap node) {
    ResolutionInterfaceType mapType = elements.getType(node);
    ResolutionDartType mapKeyType = firstType(mapType.typeArguments);
    ResolutionDartType mapValueType = secondType(mapType.typeArguments);
    bool isConst = node.isConst;
    for (Link<Node> link = node.entries.nodes;
        !link.isEmpty;
        link = link.tail) {
      LiteralMapEntry entry = link.head;
      ResolutionDartType keyType = analyze(entry.key);
      checkAssignable(entry.key, keyType, mapKeyType, isConst: isConst);
      ResolutionDartType valueType = analyze(entry.value);
      checkAssignable(entry.value, valueType, mapValueType, isConst: isConst);
    }
    return mapType;
  }

  visitNamedArgument(NamedArgument node) {
    // Named arguments are visited as part of analyzing invocations of
    // unresolved methods. For instance [: foo(a: 42); :] where 'foo' is neither
    // found in the enclosing scope nor through lookup on 'this' or
    // [: x.foo(b: 42); :] where 'foo' cannot be not found through lookup on
    // the static type of 'x'.
    return analyze(node.expression);
  }

  visitSwitchStatement(SwitchStatement node) {
    // TODO(johnniwinther): Handle reachability based on reachability of
    // switch cases.
    // TODO(johnniwinther): Provide hint of duplicate case constants.

    ResolutionDartType expressionType = analyze(node.expression);

    // Check that all the case expressions are assignable to the expression.
    bool hasDefaultCase = false;
    for (SwitchCase switchCase in node.cases) {
      if (switchCase.isDefaultCase) {
        hasDefaultCase = true;
      }
      for (Node labelOrCase in switchCase.labelsAndCases) {
        CaseMatch caseMatch = labelOrCase.asCaseMatch();
        if (caseMatch == null) continue;

        ResolutionDartType caseType = analyze(caseMatch.expression);
        checkAssignable(caseMatch, expressionType, caseType);
      }

      analyzeUntyped(switchCase);
    }

    if (!hasDefaultCase && expressionType.isEnumType) {
      compiler.enqueuer.resolution
          .addDeferredAction(new DeferredAction(executableContext, () {
        Map<ConstantValue, FieldElement> enumValues =
            <ConstantValue, FieldElement>{};
        List<FieldElement> unreferencedFields = <FieldElement>[];
        EnumClassElement enumClass = expressionType.element;
        enumClass.enumValues.forEach((EnumConstantElement field) {
          // TODO(johnniwinther): Ensure that the enum constant is computed at
          // this point.
          ConstantValue constantValue = compiler.resolver.constantCompiler
              .getConstantValueForVariable(field);
          if (constantValue == null) {
            // The field might not have been resolved.
            unreferencedFields.add(field);
          } else {
            enumValues[constantValue] = field;
          }
        });

        for (SwitchCase switchCase in node.cases) {
          for (Node labelOrCase in switchCase.labelsAndCases) {
            CaseMatch caseMatch = labelOrCase.asCaseMatch();
            if (caseMatch != null) {
              ConstantExpression caseConstant = compiler
                  .resolver.constantCompiler
                  .compileNode(caseMatch.expression, elements);
              enumValues
                  .remove(compiler.constants.getConstantValue(caseConstant));
            }
          }
        }
        unreferencedFields.addAll(enumValues.values);
        if (!unreferencedFields.isEmpty) {
          reporter.reportWarningMessage(node, MessageKind.MISSING_ENUM_CASES, {
            'enumType': expressionType,
            'enumValues': unreferencedFields.map((e) => e.name).join(', ')
          });
        }
      }));
    }
  }

  visitSwitchCase(SwitchCase node) {
    analyzeUntyped(node.statements);
  }

  visitTryStatement(TryStatement node) {
    // TODO(johnniwinther): Use reachability information of try-block,
    // catch-blocks and finally-block to compute the whether the try statement
    // is returning.
    analyzeUntyped(node.tryBlock);
    for (CatchBlock catchBlock in node.catchBlocks) {
      analyzeUntyped(catchBlock);
    }
    analyzeUntyped(node.finallyBlock);
  }

  visitCatchBlock(CatchBlock node) {
    analyzeUntyped(node.block);
  }

  visitTypedef(Typedef node) {
    // Do not typecheck [Typedef] nodes.
  }

  visitNode(Node node) {
    reporter.internalError(node,
        'Unexpected node ${node.getObjectDescription()} in the type checker.');
  }
}
