// Copyright (c) 2013, 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 simple_types_inferrer;

import '../closure.dart' show ClosureRepresentationInfo, ScopeInfo;
import '../common.dart';
import '../common/names.dart' show Identifiers, Selectors;
import '../compiler.dart' show Compiler;
import '../constants/constant_system.dart';
import '../constants/expressions.dart';
import '../constants/values.dart' show ConstantValue, IntConstantValue;
import '../elements/elements.dart';
import '../elements/entities.dart';
import '../elements/jumps.dart';
import '../elements/names.dart';
import '../elements/operators.dart' as op;
import '../elements/resolution_types.dart'
    show ResolutionDartType, ResolutionInterfaceType;
import '../js_backend/backend.dart' show JavaScriptBackend;
import '../native/native.dart' as native;
import '../resolution/semantic_visitor.dart';
import '../resolution/tree_elements.dart' show TreeElements;
import '../tree/tree.dart' as ast;
import '../types/constants.dart' show computeTypeMask;
import '../types/types.dart' show TypeMask, GlobalTypeInferenceElementData;
import '../universe/call_structure.dart' show CallStructure;
import '../universe/selector.dart' show Selector;
import '../universe/side_effects.dart' show SideEffectsBuilder;
import '../util/util.dart' show Link, Setlet;
import '../world.dart' show ClosedWorld;
import 'inferrer_engine.dart';
import 'locals_handler.dart';
import 'type_graph_nodes.dart';
import 'type_system.dart';

/// [ElementGraphBuilder] can be thought of as a type-inference graph
/// builder for a single element.
///
/// Calling [run] will start the work of visiting the body of the code to
/// construct a set of infernece-nodes that abstractly represent what the code
/// is doing.
///
/// This visitor is parameterized by an [InferenceEngine], which internally
/// decides how to represent inference nodes.
class ElementGraphBuilder extends ast.Visitor<TypeInformation>
    with
        SemanticSendResolvedMixin<TypeInformation, dynamic>,
        CompoundBulkMixin<TypeInformation, dynamic>,
        SetIfNullBulkMixin<TypeInformation, dynamic>,
        PrefixBulkMixin<TypeInformation, dynamic>,
        PostfixBulkMixin<TypeInformation, dynamic>,
        ErrorBulkMixin<TypeInformation, dynamic>,
        NewBulkMixin<TypeInformation, dynamic>,
        SetBulkMixin<TypeInformation, dynamic>
    implements SemanticSendVisitor<TypeInformation, dynamic> {
  final Compiler compiler;
  final MemberElement analyzedElement;
  final ResolvedAst resolvedAst;
  final TypeSystem<ast.Node> types;
  final Map<JumpTarget, List<LocalsHandler>> breaksFor =
      new Map<JumpTarget, List<LocalsHandler>>();
  final Map<JumpTarget, List<LocalsHandler>> continuesFor =
      new Map<JumpTarget, List<LocalsHandler>>();
  LocalsHandler<ast.Node> locals;
  final List<TypeInformation> cascadeReceiverStack =
      new List<TypeInformation>();

  TypeInformation returnType;
  bool visitingInitializers = false;
  bool isConstructorRedirect = false;
  bool seenSuperConstructorCall = false;
  final SideEffectsBuilder sideEffectsBuilder;
  final MemberElement outermostElement;
  final InferrerEngine inferrer;
  final Setlet<Entity> capturedVariables = new Setlet<Entity>();
  final GlobalTypeInferenceElementData memberData;

  ElementGraphBuilder.internal(
      MemberElement analyzedElement,
      this.resolvedAst,
      this.outermostElement,
      InferrerEngine inferrer,
      this.compiler,
      this.locals)
      : this.analyzedElement = analyzedElement,
        this.inferrer = inferrer,
        this.types = inferrer.types,
        this.memberData = inferrer.dataOfMember(analyzedElement.memberContext),
        this.sideEffectsBuilder = analyzedElement is MethodElement
            ? inferrer.closedWorldRefiner.getSideEffectsBuilder(analyzedElement)
            : new SideEffectsBuilder.free(analyzedElement) {
    assert(analyzedElement.isDeclaration);
    assert(outermostElement != null);
    assert(outermostElement.isDeclaration);
    if (locals != null) return;
    ast.Node node;
    if (resolvedAst.kind == ResolvedAstKind.PARSED) {
      node = resolvedAst.node;
    }
    FieldInitializationScope<ast.Node> fieldScope =
        analyzedElement.isGenerativeConstructor
            ? new FieldInitializationScope<ast.Node>(types)
            : null;
    locals = new LocalsHandler<ast.Node>(
        inferrer, types, compiler.options, node, fieldScope);
  }

  ElementGraphBuilder(
      MemberElement element, Compiler compiler, InferrerEngine inferrer,
      [LocalsHandler handler])
      : this.internal(element, element.resolvedAst,
            element.memberContext.declaration, inferrer, compiler, handler);

  TreeElements get elements => resolvedAst.elements;

  bool accumulateIsChecks = false;
  bool conditionIsSimple = false;
  List<ast.Send> isChecks;
  int loopLevel = 0;

  bool get inLoop => loopLevel > 0;
  bool get isThisExposed {
    return analyzedElement.isGenerativeConstructor
        ? locals.fieldScope.isThisExposed
        : true;
  }

  void set isThisExposed(value) {
    if (analyzedElement.isGenerativeConstructor) {
      locals.fieldScope.isThisExposed = value;
    }
  }

  void initializationIsIndefinite() {
    if (analyzedElement.isGenerativeConstructor) {
      locals.fieldScope.isIndefinite = true;
    }
  }

  DiagnosticReporter get reporter => compiler.reporter;

  ClosedWorld get closedWorld => inferrer.closedWorld;

  @override
  SemanticSendVisitor<TypeInformation, dynamic> get sendVisitor => this;

  @override
  TypeInformation apply(ast.Node node, _) => visit(node);

  TypeInformation visitAssert(ast.Assert node) {
    // Avoid pollution from assert statement unless enabled.
    if (!compiler.options.enableUserAssertions) {
      return null;
    }
    List<ast.Send> tests = <ast.Send>[];
    bool simpleCondition = handleCondition(node.condition, tests);
    LocalsHandler saved = locals;
    locals = new LocalsHandler.from(locals, node);
    updateIsChecks(tests, usePositive: true);

    LocalsHandler thenLocals = locals;
    locals = new LocalsHandler.from(saved, node);
    if (simpleCondition) updateIsChecks(tests, usePositive: false);
    visit(node.message);
    locals.seenReturnOrThrow = true;
    saved.mergeDiamondFlow(thenLocals, locals);
    locals = saved;
    return null;
  }

  @override
  TypeInformation bulkHandleSet(ast.SendSet node, _) {
    return handleSendSet(node);
  }

  @override
  TypeInformation bulkHandleCompound(ast.SendSet node, _) {
    return handleSendSet(node);
  }

  @override
  TypeInformation bulkHandleSetIfNull(ast.SendSet node, _) {
    return handleSendSet(node);
  }

  @override
  TypeInformation bulkHandlePrefix(ast.SendSet node, _) {
    return handleSendSet(node);
  }

  @override
  TypeInformation bulkHandlePostfix(ast.SendSet node, _) {
    return handleSendSet(node);
  }

  @override
  TypeInformation bulkHandleError(ast.Node node, ErroneousElement error, _) {
    return types.dynamicType;
  }

  TypeInformation visitNode(ast.Node node) {
    return node.visitChildren(this);
  }

  TypeInformation visit(ast.Node node) {
    return node == null ? null : node.accept(this);
  }

  TypeInformation visitLiteralString(ast.LiteralString node) {
    return types.stringLiteralType(node.dartString.slowToString());
  }

  TypeInformation visitStringJuxtaposition(ast.StringJuxtaposition node) {
    node.visitChildren(this);
    return types.stringType;
  }

  TypeInformation visitLiteralBool(ast.LiteralBool node) {
    return types.boolLiteralType(node.value);
  }

  TypeInformation visitLiteralDouble(ast.LiteralDouble node) {
    ConstantSystem constantSystem = closedWorld.constantSystem;
    // The JavaScript backend may turn this literal into an integer at
    // runtime.
    return types.getConcreteTypeFor(
        computeTypeMask(closedWorld, constantSystem.createDouble(node.value)));
  }

  TypeInformation visitLiteralInt(ast.LiteralInt node) {
    ConstantSystem constantSystem = closedWorld.constantSystem;
    // The JavaScript backend may turn this literal into a double at
    // runtime.
    return types.getConcreteTypeFor(
        computeTypeMask(closedWorld, constantSystem.createInt(node.value)));
  }

  TypeInformation visitLiteralNull(ast.LiteralNull node) {
    return types.nullType;
  }

  TypeInformation visitLiteralSymbol(ast.LiteralSymbol node) {
    return types
        .nonNullSubtype(closedWorld.commonElements.symbolImplementationClass);
  }

  @override
  void previsitDeferredAccess(ast.Send node, PrefixElement prefix, _) {
    // Deferred access does not affect inference.
  }

  TypeInformation handleTypeLiteralGet() {
    return types.typeType;
  }

  @override
  TypeInformation bulkHandleNode(ast.Node node, String message, _) {
    return internalError(node, message.replaceAll('#', '$node'));
  }

  @override
  TypeInformation visitConstantGet(
      ast.Send node, ConstantExpression constant, _) {
    return bulkHandleNode(node, "Constant read `#` unhandled.", _);
  }

  @override
  TypeInformation visitConstantInvoke(
      ast.Send node,
      ConstantExpression constant,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    return bulkHandleNode(node, "Constant invoke `#` unhandled.", _);
  }

  TypeInformation visitClassTypeLiteralGet(
      ast.Send node, ConstantExpression constant, _) {
    return handleTypeLiteralGet();
  }

  TypeInformation visitClassTypeLiteralInvoke(
      ast.Send node,
      ConstantExpression constant,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    return handleTypeLiteralInvoke(arguments);
  }

  TypeInformation visitTypedefTypeLiteralGet(
      ast.Send node, ConstantExpression constant, _) {
    return handleTypeLiteralGet();
  }

  TypeInformation visitTypedefTypeLiteralInvoke(
      ast.Send node,
      ConstantExpression constant,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    return handleTypeLiteralInvoke(arguments);
  }

  TypeInformation visitTypeVariableTypeLiteralGet(
      ast.Send node, TypeVariableElement element, _) {
    return handleTypeLiteralGet();
  }

  TypeInformation visitTypeVariableTypeLiteralInvoke(
      ast.Send node,
      TypeVariableElement element,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    return handleTypeLiteralInvoke(arguments);
  }

  TypeInformation visitDynamicTypeLiteralGet(
      ast.Send node, ConstantExpression constant, _) {
    return handleTypeLiteralGet();
  }

  TypeInformation visitDynamicTypeLiteralInvoke(
      ast.Send node,
      ConstantExpression constant,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    return handleTypeLiteralInvoke(arguments);
  }

  TypeInformation _thisType;
  TypeInformation get thisType {
    if (_thisType != null) return _thisType;
    ClassElement cls = outermostElement.enclosingClass;
    if (closedWorld.isUsedAsMixin(cls)) {
      return _thisType = types.nonNullSubtype(cls);
    } else {
      return _thisType = types.nonNullSubclass(cls);
    }
  }

  @override
  TypeInformation visitThisGet(ast.Identifier node, _) {
    return thisType;
  }

  TypeInformation visitIdentifier(ast.Identifier node) {
    if (node.isThis()) {
      return thisType;
    } else if (node.isSuper()) {
      return internalError(node, 'Unexpected expression $node.');
    } else {
      Element element = elements[node];
      if (Elements.isLocal(element)) {
        LocalElement local = element;
        return locals.use(local);
      }
      return null;
    }
  }

  void potentiallyAddIsCheck(ast.Send node) {
    if (!accumulateIsChecks) return;
    if (!Elements.isLocal(elements[node.receiver])) return;
    isChecks.add(node);
  }

  void potentiallyAddNullCheck(ast.Send node, ast.Node receiver) {
    if (!accumulateIsChecks) return;
    if (!Elements.isLocal(elements[receiver])) return;
    isChecks.add(node);
  }

  void updateIsChecks(List<ast.Node> tests, {bool usePositive}) {
    if (tests == null) return;
    for (ast.Send node in tests) {
      if (node.isTypeTest) {
        if (node.isIsNotCheck) {
          if (usePositive) continue;
        } else {
          if (!usePositive) continue;
        }
        ResolutionDartType type =
            elements.getType(node.typeAnnotationFromIsCheckOrCast);
        Element element = elements[node.receiver];
        if (Elements.isLocal(element)) {
          LocalElement local = element;
          locals.narrow(local, type, node);
        }
      } else {
        Element receiverElement = elements[node.receiver];
        Element argumentElement = elements[node.arguments.first];
        String operator = node.selector.asOperator().source;
        if ((operator == '==' && usePositive) ||
            (operator == '!=' && !usePositive)) {
          // Type the elements as null.
          if (Elements.isLocal(receiverElement)) {
            LocalElement local = receiverElement;
            locals.update(local, types.nullType, node, local.type);
          }
          if (Elements.isLocal(argumentElement)) {
            LocalElement local = argumentElement;
            locals.update(local, types.nullType, node, local.type);
          }
        } else {
          // Narrow the elements to a non-null type.
          ResolutionInterfaceType objectType =
              closedWorld.commonElements.objectType;
          if (Elements.isLocal(receiverElement)) {
            LocalElement local = receiverElement;
            locals.narrow(local, objectType, node);
          }
          if (Elements.isLocal(argumentElement)) {
            LocalElement local = argumentElement;
            locals.narrow(local, objectType, node);
          }
        }
      }
    }
  }

  @override
  TypeInformation visitIndex(
      ast.Send node, ast.Node receiver, ast.Node index, _) {
    return handleDynamicInvoke(node);
  }

  @override
  TypeInformation visitDynamicPropertyInvoke(ast.Send node, ast.Node receiver,
      ast.NodeList arguments, Selector selector, _) {
    return handleDynamicInvoke(node);
  }

  @override
  TypeInformation visitIfNotNullDynamicPropertyInvoke(ast.Send node,
      ast.Node receiver, ast.NodeList arguments, Selector selector, _) {
    return handleDynamicInvoke(node);
  }

  @override
  TypeInformation visitThisPropertyInvoke(
      ast.Send node, ast.NodeList arguments, Selector selector, _) {
    return handleDynamicInvoke(node);
  }

  @override
  TypeInformation visitIfNull(ast.Send node, ast.Node left, ast.Node right, _) {
    TypeInformation firstType = visit(left);
    TypeInformation secondType = visit(right);
    return types.allocateDiamondPhi(types.narrowNotNull(firstType), secondType);
  }

  @override
  TypeInformation visitLogicalAnd(
      ast.Send node, ast.Node left, ast.Node right, _) {
    conditionIsSimple = false;
    bool oldAccumulateIsChecks = accumulateIsChecks;
    List<ast.Send> oldIsChecks = isChecks;
    if (!accumulateIsChecks) {
      accumulateIsChecks = true;
      isChecks = <ast.Send>[];
    }
    visit(left);
    LocalsHandler saved = locals;
    locals = new LocalsHandler.from(locals, node);
    updateIsChecks(isChecks, usePositive: true);
    LocalsHandler narrowed;
    if (oldAccumulateIsChecks) {
      narrowed = new LocalsHandler.topLevelCopyOf(locals);
    } else {
      accumulateIsChecks = false;
      isChecks = oldIsChecks;
    }
    visit(right);
    if (oldAccumulateIsChecks) {
      bool invalidatedInRightHandSide(ast.Send test) {
        Element receiver = elements[test.receiver];
        if (receiver is LocalElement) {
          return narrowed.locals[receiver] != locals.locals[receiver];
        }
        return false;
      }

      isChecks.removeWhere(invalidatedInRightHandSide);
    }
    saved.mergeDiamondFlow(locals, null);
    locals = saved;
    return types.boolType;
  }

  @override
  TypeInformation visitLogicalOr(
      ast.Send node, ast.Node left, ast.Node right, _) {
    conditionIsSimple = false;
    List<ast.Send> tests = <ast.Send>[];
    bool isSimple = handleCondition(left, tests);
    LocalsHandler saved = locals;
    locals = new LocalsHandler.from(locals, node);
    if (isSimple) updateIsChecks(tests, usePositive: false);
    bool oldAccumulateIsChecks = accumulateIsChecks;
    accumulateIsChecks = false;
    visit(right);
    accumulateIsChecks = oldAccumulateIsChecks;
    saved.mergeDiamondFlow(locals, null);
    locals = saved;
    return types.boolType;
  }

  @override
  TypeInformation visitNot(ast.Send node, ast.Node expression, _) {
    bool oldAccumulateIsChecks = accumulateIsChecks;
    accumulateIsChecks = false;
    visit(expression);
    accumulateIsChecks = oldAccumulateIsChecks;
    return types.boolType;
  }

  @override
  TypeInformation visitIs(
      ast.Send node, ast.Node expression, ResolutionDartType type, _) {
    potentiallyAddIsCheck(node);
    visit(expression);
    return types.boolType;
  }

  @override
  TypeInformation visitIsNot(
      ast.Send node, ast.Node expression, ResolutionDartType type, _) {
    potentiallyAddIsCheck(node);
    visit(expression);
    return types.boolType;
  }

  @override
  TypeInformation visitAs(
      ast.Send node, ast.Node expression, ResolutionDartType type, _) {
    TypeInformation receiverType = visit(expression);
    return types.narrowType(receiverType, type);
  }

  @override
  TypeInformation visitUnary(
      ast.Send node, op.UnaryOperator operator, ast.Node expression, _) {
    return handleDynamicInvoke(node);
  }

  @override
  TypeInformation visitNotEquals(
      ast.Send node, ast.Node left, ast.Node right, _) {
    handleDynamicInvoke(node);
    return types.boolType;
  }

  @override
  TypeInformation visitEquals(ast.Send node, ast.Node left, ast.Node right, _) {
    return handleDynamicInvoke(node);
  }

  @override
  TypeInformation visitBinary(ast.Send node, ast.Node left,
      op.BinaryOperator operator, ast.Node right, _) {
    return handleDynamicInvoke(node);
  }

  // Because some nodes just visit their children, we may end up
  // visiting a type annotation, that may contain a send in case of a
  // prefixed type. Therefore we explicitly visit the type annotation
  // to avoid confusing the [ResolvedVisitor].
  visitTypeAnnotation(ast.TypeAnnotation node) {}

  TypeInformation visitConditional(ast.Conditional node) {
    List<ast.Send> tests = <ast.Send>[];
    bool simpleCondition = handleCondition(node.condition, tests);
    LocalsHandler saved = locals;
    locals = new LocalsHandler.from(locals, node);
    updateIsChecks(tests, usePositive: true);
    TypeInformation firstType = visit(node.thenExpression);
    LocalsHandler thenLocals = locals;
    locals = new LocalsHandler.from(saved, node);
    if (simpleCondition) updateIsChecks(tests, usePositive: false);
    TypeInformation secondType = visit(node.elseExpression);
    saved.mergeDiamondFlow(thenLocals, locals);
    locals = saved;
    TypeInformation type = types.allocateDiamondPhi(firstType, secondType);
    return type;
  }

  TypeInformation visitVariableDefinitions(ast.VariableDefinitions node) {
    for (Link<ast.Node> link = node.definitions.nodes;
        !link.isEmpty;
        link = link.tail) {
      ast.Node definition = link.head;
      if (definition is ast.Identifier) {
        LocalElement local = elements[definition];
        locals.update(local, types.nullType, node, local.type);
      } else {
        assert(definition.asSendSet() != null);
        handleSendSet(definition);
      }
    }
    return null;
  }

  bool handleCondition(ast.Node node, List<ast.Send> tests) {
    bool oldConditionIsSimple = conditionIsSimple;
    bool oldAccumulateIsChecks = accumulateIsChecks;
    List<ast.Send> oldIsChecks = isChecks;
    accumulateIsChecks = true;
    conditionIsSimple = true;
    isChecks = tests;
    visit(node);
    bool simpleCondition = conditionIsSimple;
    accumulateIsChecks = oldAccumulateIsChecks;
    isChecks = oldIsChecks;
    conditionIsSimple = oldConditionIsSimple;
    return simpleCondition;
  }

  TypeInformation visitIf(ast.If node) {
    List<ast.Send> tests = <ast.Send>[];
    bool simpleCondition = handleCondition(node.condition, tests);
    LocalsHandler saved = locals;
    locals = new LocalsHandler.from(locals, node);
    updateIsChecks(tests, usePositive: true);
    visit(node.thenPart);
    LocalsHandler thenLocals = locals;
    locals = new LocalsHandler.from(saved, node);
    if (simpleCondition) updateIsChecks(tests, usePositive: false);
    visit(node.elsePart);
    saved.mergeDiamondFlow(thenLocals, locals);
    locals = saved;
    return null;
  }

  void setupBreaksAndContinues(JumpTarget element) {
    if (element == null) return;
    if (element.isContinueTarget) continuesFor[element] = <LocalsHandler>[];
    if (element.isBreakTarget) breaksFor[element] = <LocalsHandler>[];
  }

  void clearBreaksAndContinues(JumpTarget element) {
    continuesFor.remove(element);
    breaksFor.remove(element);
  }

  List<LocalsHandler> getBreaks(JumpTarget element) {
    List<LocalsHandler> list = <LocalsHandler>[locals];
    if (element == null) return list;
    if (!element.isBreakTarget) return list;
    return list..addAll(breaksFor[element]);
  }

  List<LocalsHandler> getLoopBackEdges(JumpTarget element) {
    List<LocalsHandler> list = <LocalsHandler>[locals];
    if (element == null) return list;
    if (!element.isContinueTarget) return list;
    return list..addAll(continuesFor[element]);
  }

  TypeInformation handleLoop(ast.Node node, void logic()) {
    loopLevel++;
    bool changed = false;
    JumpTarget target = elements.getTargetDefinition(node);
    LocalsHandler saved = locals;
    saved.startLoop(node);
    do {
      // Setup (and clear in case of multiple iterations of the loop)
      // the lists of breaks and continues seen in the loop.
      setupBreaksAndContinues(target);
      locals = new LocalsHandler.from(saved, node);
      logic();
      changed = saved.mergeAll(getLoopBackEdges(target));
    } while (changed);
    loopLevel--;
    saved.endLoop(node);
    bool keepOwnLocals = node.asDoWhile() == null;
    saved.mergeAfterBreaks(getBreaks(target), keepOwnLocals: keepOwnLocals);
    locals = saved;
    clearBreaksAndContinues(target);
    return null;
  }

  TypeInformation visitWhile(ast.While node) {
    return handleLoop(node, () {
      List<ast.Send> tests = <ast.Send>[];
      handleCondition(node.condition, tests);
      updateIsChecks(tests, usePositive: true);
      visit(node.body);
    });
  }

  TypeInformation visitDoWhile(ast.DoWhile node) {
    return handleLoop(node, () {
      visit(node.body);
      List<ast.Send> tests = <ast.Send>[];
      handleCondition(node.condition, tests);
      // TODO(29309): This condition appears to strengthen both the back-edge
      // and exit-edge. For now, avoid strengthening on the condition until the
      // proper fix is found.
      //
      //     updateIsChecks(tests, usePositive: true);
    });
  }

  TypeInformation visitFor(ast.For node) {
    visit(node.initializer);
    return handleLoop(node, () {
      List<ast.Send> tests = <ast.Send>[];
      handleCondition(node.condition, tests);
      updateIsChecks(tests, usePositive: true);
      visit(node.body);
      visit(node.update);
    });
  }

  TypeInformation visitTryStatement(ast.TryStatement node) {
    LocalsHandler saved = locals;
    locals = new LocalsHandler.from(locals, node, useOtherTryBlock: false);
    initializationIsIndefinite();
    visit(node.tryBlock);
    saved.mergeDiamondFlow(locals, null);
    locals = saved;
    for (ast.Node catchBlock in node.catchBlocks) {
      saved = locals;
      locals = new LocalsHandler.from(locals, catchBlock);
      visit(catchBlock);
      saved.mergeDiamondFlow(locals, null);
      locals = saved;
    }
    visit(node.finallyBlock);
    return null;
  }

  TypeInformation visitThrow(ast.Throw node) {
    node.visitChildren(this);
    locals.seenReturnOrThrow = true;
    return types.nonNullEmpty();
  }

  TypeInformation visitCatchBlock(ast.CatchBlock node) {
    ast.Node exception = node.exception;
    if (exception != null) {
      ResolutionDartType type = elements.getType(node.type);
      TypeInformation mask;
      if (type == null || type.treatAsDynamic || type.isTypeVariable) {
        mask = types.dynamicType;
      } else {
        ResolutionInterfaceType interfaceType = type;
        mask = types.nonNullSubtype(interfaceType.element);
      }
      LocalElement local = elements[exception];
      locals.update(local, mask, node, local.type);
    }
    ast.Node trace = node.trace;
    if (trace != null) {
      LocalElement local = elements[trace];
      locals.update(local, types.dynamicType, node, local.type);
    }
    visit(node.block);
    return null;
  }

  TypeInformation visitParenthesizedExpression(
      ast.ParenthesizedExpression node) {
    return visit(node.expression);
  }

  TypeInformation visitBlock(ast.Block node) {
    if (node.statements != null) {
      for (ast.Node statement in node.statements) {
        visit(statement);
        if (locals.aborts) break;
      }
    }
    return null;
  }

  TypeInformation visitLabeledStatement(ast.LabeledStatement node) {
    ast.Statement body = node.statement;
    if (body is ast.Loop ||
        body is ast.SwitchStatement ||
        Elements.isUnusedLabel(node, elements)) {
      // Loops and switches handle their own labels.
      visit(body);
    } else {
      JumpTarget targetElement = elements.getTargetDefinition(body);
      setupBreaksAndContinues(targetElement);
      visit(body);
      locals.mergeAfterBreaks(getBreaks(targetElement));
      clearBreaksAndContinues(targetElement);
    }
    return null;
  }

  TypeInformation visitBreakStatement(ast.BreakStatement node) {
    JumpTarget target = elements.getTargetOf(node);
    locals.seenBreakOrContinue = true;
    // Do a deep-copy of the locals, because the code following the
    // break will change them.
    breaksFor[target].add(new LocalsHandler.deepCopyOf(locals));
    return null;
  }

  TypeInformation visitContinueStatement(ast.ContinueStatement node) {
    JumpTarget target = elements.getTargetOf(node);
    locals.seenBreakOrContinue = true;
    // Do a deep-copy of the locals, because the code following the
    // continue will change them.
    continuesFor[target].add(new LocalsHandler.deepCopyOf(locals));
    return null;
  }

  internalError(Spannable node, String reason) {
    reporter.internalError(node, reason);
  }

  TypeInformation visitSwitchStatement(ast.SwitchStatement node) {
    visit(node.parenthesizedExpression);

    setupBreaksAndContinues(elements.getTargetDefinition(node));
    if (Elements.switchStatementHasContinue(node, elements)) {
      void forEachLabeledCase(void action(JumpTarget target)) {
        for (ast.SwitchCase switchCase in node.cases) {
          for (ast.Node labelOrCase in switchCase.labelsAndCases) {
            if (labelOrCase.asLabel() == null) continue;
            LabelDefinition labelElement =
                elements.getLabelDefinition(labelOrCase);
            if (labelElement != null) {
              action(labelElement.target);
            }
          }
        }
      }

      forEachLabeledCase((JumpTarget target) {
        setupBreaksAndContinues(target);
      });

      // If the switch statement has a continue, we conservatively
      // visit all cases and update [locals] until we have reached a
      // fixed point.
      bool changed;
      locals.startLoop(node);
      do {
        changed = false;
        for (ast.Node switchCase in node.cases) {
          LocalsHandler saved = locals;
          locals = new LocalsHandler.from(locals, switchCase);
          visit(switchCase);
          changed = saved.mergeAll([locals]) || changed;
          locals = saved;
        }
      } while (changed);
      locals.endLoop(node);

      forEachLabeledCase((JumpTarget target) {
        clearBreaksAndContinues(target);
      });
    } else {
      LocalsHandler saved = locals;
      List<LocalsHandler> localsToMerge = <LocalsHandler>[];
      bool hasDefaultCase = false;

      for (ast.SwitchCase switchCase in node.cases) {
        if (switchCase.isDefaultCase) {
          hasDefaultCase = true;
        }
        locals = new LocalsHandler.from(saved, switchCase);
        visit(switchCase);
        localsToMerge.add(locals);
      }
      saved.mergeAfterBreaks(localsToMerge, keepOwnLocals: !hasDefaultCase);
      locals = saved;
    }
    clearBreaksAndContinues(elements.getTargetDefinition(node));
    return null;
  }

  TypeInformation visitCascadeReceiver(ast.CascadeReceiver node) {
    var type = visit(node.expression);
    cascadeReceiverStack.add(type);
    return type;
  }

  TypeInformation visitCascade(ast.Cascade node) {
    // Ignore the result of the cascade send and return the type of the cascade
    // receiver.
    visit(node.expression);
    return cascadeReceiverStack.removeLast();
  }

  void analyzeSuperConstructorCall(ConstructorElement target) {
    assert(target.isDeclaration);
    inferrer.analyze(target);
    isThisExposed = isThisExposed || inferrer.checkIfExposesThis(target);
  }

  TypeInformation run() {
    var node;
    if (resolvedAst.kind == ResolvedAstKind.PARSED) {
      node = resolvedAst.node;
    }
    ast.Expression initializer;
    if (analyzedElement.isField) {
      initializer = resolvedAst.body;
      if (initializer == null) {
        // Eagerly bailout, because computing the closure data only
        // works for functions and field assignments.
        return types.nullType;
      }
    }
    // Update the locals that are boxed in [locals]. These locals will
    // be handled specially, in that we are computing their LUB at
    // each update, and reading them yields the type that was found in a
    // previous analysis of [outermostElement].
    ScopeInfo scopeInfo = compiler.backendStrategy.closureDataLookup
        .getScopeInfo(analyzedElement);
    scopeInfo.forEachBoxedVariable((variable, field) {
      locals.setCapturedAndBoxed(variable, field);
    });
    if (analyzedElement.isField) {
      return visit(initializer);
    }

    MethodElement function = analyzedElement.implementation;
    FunctionSignature signature = function.functionSignature;
    signature.forEachOptionalParameter((FormalElement _element) {
      ParameterElement parameter = _element;
      ast.Expression defaultValue = parameter.initializer;
      // TODO(25566): The default value of a parameter of a redirecting factory
      // constructor comes from the corresponding parameter of the target.

      // If this is a default value from a different context (because
      // the current function is synthetic, e.g., a constructor from
      // a mixin application), we have to start a new inferrer visitor
      // with the correct context.
      // TODO(johnniwinther): Remove once function signatures are fixed.
      ElementGraphBuilder visitor = this;
      if (inferrer.hasAlreadyComputedTypeOfParameterDefault(parameter)) return;

      FunctionElement declaration = parameter.functionDeclaration.declaration;
      MethodElement declarationMethod = declaration is LocalFunctionElement
          ? declaration.callMethod
          : declaration;
      bool needNewContext = declarationMethod != analyzedElement;
      if (needNewContext) {
        assert(
            declarationMethod is ConstructorElement,
            failedAt(
                parameter,
                "Unexpected function declaration "
                "${declarationMethod}, expected ${analyzedElement}."));
        visitor =
            new ElementGraphBuilder(declarationMethod, compiler, inferrer);
      }
      TypeInformation type =
          (defaultValue == null) ? types.nullType : visitor.visit(defaultValue);
      inferrer.setDefaultTypeOfParameter(parameter, type,
          isInstanceMember: function.isInstanceMember);
    });

    if (closedWorld.nativeData.isNativeMember(analyzedElement)) {
      // Native methods do not have a body, and we currently just say
      // they return dynamic.
      return types.dynamicType;
    }

    if (analyzedElement.isGenerativeConstructor) {
      ConstructorElement analyzedConstructor = analyzedElement;
      isThisExposed = false;
      signature.forEachParameter((FormalElement _element) {
        ParameterElement element = _element;
        TypeInformation parameterType = inferrer.typeOfParameter(element);
        if (element.isInitializingFormal) {
          InitializingFormalElement initializingFormal = element;
          if (initializingFormal.fieldElement.isFinal) {
            inferrer.recordTypeOfField(
                initializingFormal.fieldElement, parameterType);
          } else {
            locals.updateField(initializingFormal.fieldElement, parameterType);
            inferrer.recordTypeOfField(
                initializingFormal.fieldElement, parameterType);
          }
        }
        locals.update(element, parameterType, node, element.type);
      });
      ClassElement cls = analyzedConstructor.enclosingClass;
      Spannable spannable = node;
      if (analyzedConstructor.isSynthesized) {
        spannable = analyzedConstructor;
        synthesizeForwardingCall(
            spannable, analyzedConstructor.definingConstructor);
      } else {
        visitingInitializers = true;
        if (node.initializers != null) {
          for (ast.Node initializer in node.initializers) {
            ast.SendSet fieldInitializer = initializer.asSendSet();
            if (fieldInitializer != null) {
              handleSendSet(fieldInitializer);
            } else {
              Element element = elements[initializer];
              handleConstructorSend(initializer, element);
            }
          }
        }
        visitingInitializers = false;
        // For a generative constructor like: `Foo();`, we synthesize
        // a call to the default super constructor (the one that takes
        // no argument). Resolution ensures that such a constructor
        // exists.
        if (!isConstructorRedirect &&
            !seenSuperConstructorCall &&
            !cls.isObject) {
          ConstructorElement target = cls.superclass.lookupDefaultConstructor();
          ArgumentsTypes arguments = new ArgumentsTypes([], {});
          analyzeSuperConstructorCall(target);
          inferrer.registerCalledMember(node, null, null, outermostElement,
              target, arguments, sideEffectsBuilder, inLoop);
        }
        visit(node.body);
        inferrer.recordExposesThis(analyzedConstructor, isThisExposed);
      }
      if (!isConstructorRedirect) {
        // Iterate over all instance fields, and give a null type to
        // fields that we haven't initialized for sure.
        cls.forEachInstanceField((_, FieldElement field) {
          if (field.isFinal) return;
          TypeInformation type = locals.fieldScope.readField(field);
          ResolvedAst resolvedAst = field.resolvedAst;
          if (type == null &&
              (resolvedAst.body == null ||
                  resolvedAst.body is ast.LiteralNull)) {
            inferrer.recordTypeOfField(field, types.nullType);
          }
        });
      }
      if (analyzedElement.isGenerativeConstructor && cls.isAbstract) {
        if (closedWorld.isInstantiated(cls)) {
          returnType = types.nonNullSubclass(cls);
        } else {
          // TODO(johnniwinther): Avoid analyzing [analyzedElement] in this
          // case; it's never called.
          returnType = types.nonNullEmpty();
        }
      } else {
        returnType = types.nonNullExact(cls);
      }
    } else {
      signature.forEachParameter((FormalElement _element) {
        ParameterElement element = _element;
        locals.update(
            element, inferrer.typeOfParameter(element), node, element.type);
      });
      visit(node.body);
      switch (function.asyncMarker) {
        case AsyncMarker.SYNC:
          if (returnType == null) {
            // No return in the body.
            returnType = locals.seenReturnOrThrow
                ? types.nonNullEmpty() // Body always throws.
                : types.nullType;
          } else if (!locals.seenReturnOrThrow) {
            // We haven't seen returns on all branches. So the method may
            // also return null.
            recordReturnType(types.nullType);
          }
          break;

        case AsyncMarker.SYNC_STAR:
          // TODO(asgerf): Maybe make a ContainerTypeMask for these? The type
          //               contained is the method body's return type.
          recordReturnType(types.syncStarIterableType);
          break;

        case AsyncMarker.ASYNC:
          recordReturnType(types.asyncFutureType);
          break;

        case AsyncMarker.ASYNC_STAR:
          recordReturnType(types.asyncStarStreamType);
          break;
      }
    }

    assert(breaksFor.isEmpty);
    assert(continuesFor.isEmpty);
    return returnType;
  }

  TypeInformation visitFunctionExpression(ast.FunctionExpression node) {
    // We loose track of [this] in closures (see issue 20840). To be on
    // the safe side, we mark [this] as exposed here. We could do better by
    // analyzing the closure.
    // TODO(herhut): Analyze whether closure exposes this.
    isThisExposed = true;
    LocalFunctionElement element = elements.getFunctionDefinition(node);
    // We don't put the closure in the work queue of the
    // inferrer, because it will share information with its enclosing
    // method, like for example the types of local variables.
    LocalsHandler closureLocals =
        new LocalsHandler.from(locals, node, useOtherTryBlock: false);
    ElementGraphBuilder visitor = new ElementGraphBuilder(
        element.callMethod, compiler, inferrer, closureLocals);
    visitor.run();
    inferrer.recordReturnType(element.callMethod, visitor.returnType);

    // Record the types of captured non-boxed variables. Types of
    // these variables may already be there, because of an analysis of
    // a previous closure.
    ClosureRepresentationInfo nestedClosureData =
        compiler.backendStrategy.closureDataLookup.getClosureInfo(node);
    nestedClosureData.forEachFreeVariable((variable, field) {
      if (!nestedClosureData.isVariableBoxed(variable)) {
        if (variable == nestedClosureData.thisLocal) {
          inferrer.recordTypeOfField(field, thisType);
        }
        // The type is null for type parameters.
        if (locals.locals[variable] == null) return;
        inferrer.recordTypeOfField(field, locals.locals[variable]);
      }
      capturedVariables.add(variable);
    });

    return inferrer.concreteTypes.putIfAbsent(node, () {
      return types.allocateClosure(element.callMethod);
    });
  }

  TypeInformation visitFunctionDeclaration(ast.FunctionDeclaration node) {
    LocalFunctionElement element =
        elements.getFunctionDefinition(node.function);
    TypeInformation type =
        inferrer.concreteTypes.putIfAbsent(node.function, () {
      return types.allocateClosure(element.callMethod);
    });
    locals.update(element, type, node, element.type);
    visit(node.function);
    return type;
  }

  TypeInformation visitStringInterpolation(ast.StringInterpolation node) {
    // Interpolation could have any effects since it could call any toString()
    // method.
    // TODO(sra): This could be modelled by a call to toString() but with a
    // guaranteed String return type.  Interpolation of known types would get
    // specialized effects.  This would not currently be effective since the JS
    // code in the toString methods for intercepted primitive types is assumed
    // to have all effects.  Effect annotations on JS code would be needed to
    // get the benefit.
    sideEffectsBuilder.setAllSideEffects();
    node.visitChildren(this);
    return types.stringType;
  }

  TypeInformation visitLiteralList(ast.LiteralList node) {
    // We only set the type once. We don't need to re-visit the children
    // when re-analyzing the node.
    return inferrer.concreteTypes.putIfAbsent(node, () {
      TypeInformation elementType;
      int length = 0;
      for (ast.Node element in node.elements.nodes) {
        TypeInformation type = visit(element);
        elementType = elementType == null
            ? types.allocatePhi(null, null, type, isTry: false)
            : types.addPhiInput(null, elementType, type);
        length++;
      }
      elementType = elementType == null
          ? types.nonNullEmpty()
          : types.simplifyPhi(null, null, elementType);
      TypeInformation containerType =
          node.isConst ? types.constListType : types.growableListType;
      return types.allocateList(
          containerType, node, outermostElement, elementType, length);
    });
  }

  TypeInformation visitLiteralMap(ast.LiteralMap node) {
    return inferrer.concreteTypes.putIfAbsent(node, () {
      ast.NodeList entries = node.entries;
      List keyTypes = [];
      List valueTypes = [];

      for (ast.LiteralMapEntry entry in entries) {
        keyTypes.add(visit(entry.key));
        valueTypes.add(visit(entry.value));
      }

      TypeInformation type = node.isConst ? types.constMapType : types.mapType;
      return types.allocateMap(
          type, node, outermostElement, keyTypes, valueTypes);
    });
  }

  bool isThisOrSuper(ast.Node node) => node.isThis() || node.isSuper();

  bool isInClassOrSubclass(Element element) {
    ClassElement cls = outermostElement.enclosingClass;
    ClassElement enclosing = element.enclosingClass;
    return closedWorld.isSubclassOf(enclosing, cls);
  }

  void checkIfExposesThis(Selector selector, TypeMask mask) {
    if (isThisExposed) return;
    inferrer.forEachElementMatching(selector, mask, (MemberEntity element) {
      if (element.isField) {
        FieldElement field = element;
        ResolvedAst elementResolvedAst = field.resolvedAst;
        if (!selector.isSetter &&
            isInClassOrSubclass(field) &&
            !field.isFinal &&
            locals.fieldScope.readField(field) == null &&
            elementResolvedAst.body == null) {
          // If the field is being used before this constructor
          // actually had a chance to initialize it, say it can be
          // null.
          inferrer.recordTypeOfField(field, types.nullType);
        }
        // Accessing a field does not expose [:this:].
        return true;
      }
      // TODO(ngeoffray): We could do better here if we knew what we
      // are calling does not expose this.
      isThisExposed = true;
      return false;
    });
  }

  bool get inInstanceContext {
    return (outermostElement.isInstanceMember && !outermostElement.isField) ||
        outermostElement.isGenerativeConstructor;
  }

  bool treatAsInstanceMember(Element element) {
    return (Elements.isUnresolved(element) && inInstanceContext) ||
        (element != null && element.isInstanceMember);
  }

  TypeInformation handleSendSet(ast.SendSet node) {
    Element element = elements[node];
    if (!Elements.isUnresolved(element) && element.impliesType) {
      node.visitChildren(this);
      return types.dynamicType;
    }

    Selector getterSelector = elements.getGetterSelectorInComplexSendSet(node);
    TypeMask getterMask = memberData.typeOfGetter(node);
    TypeMask operatorMask = memberData.typeOfOperator(node);
    Selector setterSelector = elements.getSelector(node);
    TypeMask setterMask = memberData.typeOfSend(node);

    String op = node.assignmentOperator.source;
    bool isIncrementOrDecrement = op == '++' || op == '--';

    TypeInformation receiverType;
    bool isCallOnThis = false;
    if (node.receiver == null) {
      if (treatAsInstanceMember(element)) {
        receiverType = thisType;
        isCallOnThis = true;
      }
    } else {
      if (node.receiver != null) {
        Element receiver = elements[node.receiver];
        if (receiver is! PrefixElement && receiver is! ClassElement) {
          // TODO(johnniwinther): Avoid blindly recursing on the receiver.
          receiverType = visit(node.receiver);
        }
      }
      isCallOnThis = isThisOrSuper(node.receiver);
    }

    TypeInformation rhsType;

    if (isIncrementOrDecrement) {
      rhsType = types.uint31Type;
      if (node.isIndex) visit(node.arguments.head);
    } else if (node.isIndex) {
      visit(node.arguments.head);
      rhsType = visit(node.arguments.tail.head);
    } else {
      rhsType = visit(node.arguments.head);
    }

    if (!visitingInitializers && !isThisExposed) {
      for (ast.Node node in node.arguments) {
        if (isThisOrSuper(node)) {
          isThisExposed = true;
          break;
        }
      }
      if (!isThisExposed && isCallOnThis) {
        checkIfExposesThis(
            setterSelector, types.newTypedSelector(receiverType, setterMask));
        if (getterSelector != null) {
          checkIfExposesThis(
              getterSelector, types.newTypedSelector(receiverType, getterMask));
        }
      }
    }

    if (node.isIndex) {
      return internalError(node, "Unexpected index operation");
    } else if (op == '=') {
      return handlePlainAssignment(node, element, setterSelector, setterMask,
          receiverType, rhsType, node.arguments.head);
    } else {
      // [foo ??= bar], [: foo++ :] or [: foo += 1 :].
      TypeInformation getterType;
      TypeInformation newType;

      if (Elements.isMalformed(element)) return types.dynamicType;

      if (Elements.isStaticOrTopLevelField(element)) {
        Element getterElement = elements[node.selector];
        getterType = handleStaticSend(
            node, getterSelector, getterMask, getterElement, null);
      } else if (Elements.isUnresolved(element) ||
          element.isSetter ||
          element.isField) {
        getterType = handleDynamicSend(CallType.complex, node, getterSelector,
            getterMask, receiverType, null);
      } else if (element.isLocal) {
        LocalElement local = element;
        getterType = locals.use(local);
      } else {
        // Bogus SendSet, for example [: myMethod += 42 :].
        getterType = types.dynamicType;
      }

      if (op == '??=') {
        newType = types.allocateDiamondPhi(getterType, rhsType);
      } else {
        Selector operatorSelector =
            elements.getOperatorSelectorInComplexSendSet(node);
        newType = handleDynamicSend(CallType.complex, node, operatorSelector,
            operatorMask, getterType, new ArgumentsTypes([rhsType], null));
      }

      if (Elements.isStaticOrTopLevelField(element)) {
        handleStaticSend(node, setterSelector, setterMask, element,
            new ArgumentsTypes([newType], null));
      } else if (Elements.isUnresolved(element) ||
          element.isSetter ||
          element.isField) {
        handleDynamicSend(CallType.complex, node, setterSelector, setterMask,
            receiverType, new ArgumentsTypes([newType], null));
      } else if (element.isLocal) {
        LocalElement local = element;
        locals.update(local, newType, node, local.type,
            isSetIfNull: node.isIfNullAssignment);
      }

      if (node.isPostfix) {
        if (node.isConditional) {
          return getterType;
        } else {
          // We have just successfully performed a `+ 1` operation on the getter
          // so we know it to be not `null`.
          return types.narrowNotNull(getterType);
        }
      } else {
        return newType;
      }
    }
  }

  /// Handle compound index set, like `foo[0] += 42` or `foo[0]++`.
  TypeInformation handleCompoundIndexSet(
      ast.SendSet node,
      TypeInformation receiverType,
      TypeInformation indexType,
      TypeInformation rhsType) {
    Selector getterSelector = elements.getGetterSelectorInComplexSendSet(node);

    TypeMask getterMask = memberData.typeOfGetter(node);
    Selector operatorSelector =
        elements.getOperatorSelectorInComplexSendSet(node);
    TypeMask operatorMask = memberData.typeOfOperator(node);
    Selector setterSelector = elements.getSelector(node);
    TypeMask setterMask = memberData.typeOfSend(node);

    TypeInformation getterType = handleDynamicSend(
        CallType.complex,
        node,
        getterSelector,
        getterMask,
        receiverType,
        new ArgumentsTypes([indexType], null));

    TypeInformation returnType;
    if (node.isIfNullAssignment) {
      returnType = types.allocateDiamondPhi(getterType, rhsType);
    } else {
      returnType = handleDynamicSend(CallType.complex, node, operatorSelector,
          operatorMask, getterType, new ArgumentsTypes([rhsType], null));
    }
    handleDynamicSend(CallType.complex, node, setterSelector, setterMask,
        receiverType, new ArgumentsTypes([indexType, returnType], null));

    if (node.isPostfix) {
      return getterType;
    } else {
      return returnType;
    }
  }

  /// Handle compound prefix/postfix operations, like `a[0]++`.
  TypeInformation handleCompoundPrefixPostfix(
      ast.Send node, TypeInformation receiverType, TypeInformation indexType) {
    return handleCompoundIndexSet(
        node, receiverType, indexType, types.uint31Type);
  }

  @override
  TypeInformation visitIndexPostfix(ast.Send node, ast.Node receiver,
      ast.Node index, op.IncDecOperator operator, _) {
    TypeInformation receiverType = visit(receiver);
    TypeInformation indexType = visit(index);
    return handleCompoundPrefixPostfix(node, receiverType, indexType);
  }

  @override
  TypeInformation visitIndexPrefix(ast.Send node, ast.Node receiver,
      ast.Node index, op.IncDecOperator operator, _) {
    TypeInformation receiverType = visit(receiver);
    TypeInformation indexType = visit(index);
    return handleCompoundPrefixPostfix(node, receiverType, indexType);
  }

  @override
  TypeInformation visitCompoundIndexSet(ast.SendSet node, ast.Node receiver,
      ast.Node index, op.AssignmentOperator operator, ast.Node rhs, _) {
    TypeInformation receiverType = visit(receiver);
    TypeInformation indexType = visit(index);
    TypeInformation rhsType = visit(rhs);
    return handleCompoundIndexSet(node, receiverType, indexType, rhsType);
  }

  @override
  TypeInformation visitIndexSetIfNull(
      ast.SendSet node, ast.Node receiver, ast.Node index, ast.Node rhs, _) {
    TypeInformation receiverType = visit(receiver);
    TypeInformation indexType = visit(index);
    TypeInformation rhsType = visit(rhs);
    return handleCompoundIndexSet(node, receiverType, indexType, rhsType);
  }

  @override
  TypeInformation visitSuperIndexPrefix(ast.Send node, MethodElement getter,
      MethodElement setter, ast.Node index, op.IncDecOperator operator, _) {
    TypeInformation indexType = visit(index);
    return handleSuperIndexPrefixPostfix(node, getter, setter, indexType);
  }

  @override
  TypeInformation visitSuperIndexPostfix(ast.Send node, MethodElement getter,
      MethodElement setter, ast.Node index, op.IncDecOperator operator, _) {
    TypeInformation indexType = visit(index);
    return handleSuperIndexPrefixPostfix(node, getter, setter, indexType);
  }

  /// Handle compound prefix/postfix operations, like `super[0]++`.
  TypeInformation handleSuperIndexPrefixPostfix(ast.Send node, Element getter,
      Element setter, TypeInformation indexType) {
    return _handleSuperCompoundIndexSet(
        node, getter, setter, indexType, types.uint31Type);
  }

  /// Handle compound super index set, like `super[42] =+ 2`.
  TypeInformation handleSuperCompoundIndexSet(ast.SendSet node, Element getter,
      Element setter, ast.Node index, ast.Node rhs) {
    TypeInformation indexType = visit(index);
    TypeInformation rhsType = visit(rhs);
    return _handleSuperCompoundIndexSet(
        node, getter, setter, indexType, rhsType);
  }

  TypeInformation _handleSuperCompoundIndexSet(ast.SendSet node, Element getter,
      Element setter, TypeInformation indexType, TypeInformation rhsType) {
    Selector getterSelector = elements.getGetterSelectorInComplexSendSet(node);

    TypeMask getterMask = memberData.typeOfGetter(node);
    Selector setterSelector = elements.getSelector(node);
    TypeMask setterMask = memberData.typeOfSend(node);

    TypeInformation getterType = handleSuperSend(node, getterSelector,
        getterMask, getter, new ArgumentsTypes([indexType], null));

    TypeInformation returnType;
    if (node.isIfNullAssignment) {
      returnType = types.allocateDiamondPhi(getterType, rhsType);
    } else {
      Selector operatorSelector =
          elements.getOperatorSelectorInComplexSendSet(node);
      TypeMask operatorMask = memberData.typeOfOperator(node);
      returnType = handleDynamicSend(CallType.complex, node, operatorSelector,
          operatorMask, getterType, new ArgumentsTypes([rhsType], null));
    }
    handleSuperSend(node, setterSelector, setterMask, setter,
        new ArgumentsTypes([indexType, returnType], null));

    return node.isPostfix ? getterType : returnType;
  }

  TypeInformation handleSuperSend(ast.Node node, Selector selector,
      TypeMask mask, Element element, ArgumentsTypes arguments) {
    if (element.isMalformed) {
      return handleSuperNoSuchMethod(node, selector, mask, arguments);
    } else {
      return handleStaticSend(node, selector, mask, element, arguments);
    }
  }

  @override
  TypeInformation visitSuperCompoundIndexSet(
      ast.SendSet node,
      MethodElement getter,
      MethodElement setter,
      ast.Node index,
      op.AssignmentOperator operator,
      ast.Node rhs,
      _) {
    return handleSuperCompoundIndexSet(node, getter, setter, index, rhs);
  }

  @override
  TypeInformation visitSuperIndexSetIfNull(
      ast.SendSet node,
      MethodElement getter,
      MethodElement setter,
      ast.Node index,
      ast.Node rhs,
      _) {
    return handleSuperCompoundIndexSet(node, getter, setter, index, rhs);
  }

  @override
  TypeInformation visitUnresolvedSuperCompoundIndexSet(
      ast.SendSet node,
      Element element,
      ast.Node index,
      op.AssignmentOperator operator,
      ast.Node rhs,
      _) {
    return handleSuperCompoundIndexSet(node, element, element, index, rhs);
  }

  @override
  TypeInformation visitUnresolvedSuperIndexSetIfNull(
      ast.Send node, Element element, ast.Node index, ast.Node rhs, _) {
    return handleSuperCompoundIndexSet(node, element, element, index, rhs);
  }

  @override
  TypeInformation visitUnresolvedSuperGetterCompoundIndexSet(
      ast.SendSet node,
      Element element,
      MethodElement setter,
      ast.Node index,
      op.AssignmentOperator operator,
      ast.Node rhs,
      _) {
    return handleSuperCompoundIndexSet(node, element, setter, index, rhs);
  }

  @override
  TypeInformation visitUnresolvedSuperGetterIndexSetIfNull(ast.SendSet node,
      Element element, MethodElement setter, ast.Node index, ast.Node rhs, _) {
    return handleSuperCompoundIndexSet(node, element, setter, index, rhs);
  }

  @override
  TypeInformation visitUnresolvedSuperSetterCompoundIndexSet(
      ast.SendSet node,
      MethodElement getter,
      Element element,
      ast.Node index,
      op.AssignmentOperator operator,
      ast.Node rhs,
      _) {
    return handleSuperCompoundIndexSet(node, getter, element, index, rhs);
  }

  @override
  TypeInformation visitUnresolvedSuperSetterIndexSetIfNull(ast.SendSet node,
      MethodElement getter, Element element, ast.Node index, ast.Node rhs, _) {
    return handleSuperCompoundIndexSet(node, getter, element, index, rhs);
  }

  @override
  TypeInformation visitUnresolvedSuperIndexPrefix(ast.Send node,
      Element element, ast.Node index, op.IncDecOperator operator, _) {
    TypeInformation indexType = visit(index);
    return handleSuperIndexPrefixPostfix(node, element, element, indexType);
  }

  @override
  TypeInformation visitUnresolvedSuperGetterIndexPrefix(
      ast.SendSet node,
      Element element,
      MethodElement setter,
      ast.Node index,
      op.IncDecOperator operator,
      _) {
    TypeInformation indexType = visit(index);
    return handleSuperIndexPrefixPostfix(node, element, setter, indexType);
  }

  @override
  TypeInformation visitUnresolvedSuperSetterIndexPrefix(
      ast.SendSet node,
      MethodElement getter,
      Element element,
      ast.Node index,
      op.IncDecOperator operator,
      _) {
    TypeInformation indexType = visit(index);
    return handleSuperIndexPrefixPostfix(node, getter, element, indexType);
  }

  @override
  TypeInformation visitUnresolvedSuperIndexPostfix(ast.Send node,
      Element element, ast.Node index, op.IncDecOperator operator, _) {
    TypeInformation indexType = visit(index);
    return handleSuperIndexPrefixPostfix(node, element, element, indexType);
  }

  @override
  TypeInformation visitUnresolvedSuperGetterIndexPostfix(
      ast.SendSet node,
      Element element,
      MethodElement setter,
      ast.Node index,
      op.IncDecOperator operator,
      _) {
    TypeInformation indexType = visit(index);
    return handleSuperIndexPrefixPostfix(node, element, setter, indexType);
  }

  @override
  TypeInformation visitUnresolvedSuperSetterIndexPostfix(
      ast.SendSet node,
      MethodElement getter,
      Element element,
      ast.Node index,
      op.IncDecOperator operator,
      _) {
    TypeInformation indexType = visit(index);
    return handleSuperIndexPrefixPostfix(node, getter, element, indexType);
  }

  @override
  TypeInformation visitSuperFieldCompound(ast.Send node, FieldElement field,
      op.AssignmentOperator operator, ast.Node rhs, _) {
    return handleSuperCompound(node, field, field, rhs);
  }

  @override
  TypeInformation visitSuperFieldSetterCompound(
      ast.Send node,
      FieldElement field,
      SetterElement setter,
      op.AssignmentOperator operator,
      ast.Node rhs,
      _) {
    return handleSuperCompound(node, field, setter, rhs);
  }

  @override
  TypeInformation visitSuperGetterFieldCompound(
      ast.Send node,
      GetterElement getter,
      FieldElement field,
      op.AssignmentOperator operator,
      ast.Node rhs,
      _) {
    return handleSuperCompound(node, getter, field, rhs);
  }

  @override
  TypeInformation visitSuperGetterSetterCompound(
      ast.Send node,
      GetterElement getter,
      SetterElement setter,
      op.AssignmentOperator operator,
      ast.Node rhs,
      _) {
    return handleSuperCompound(node, getter, setter, rhs);
  }

  @override
  TypeInformation visitSuperMethodSetterCompound(
      ast.Send node,
      FunctionElement method,
      SetterElement setter,
      op.AssignmentOperator operator,
      ast.Node rhs,
      _) {
    return handleSuperCompound(node, method, setter, rhs);
  }

  @override
  TypeInformation visitUnresolvedSuperCompound(ast.Send node, Element element,
      op.AssignmentOperator operator, ast.Node rhs, _) {
    return handleSuperCompound(node, element, element, rhs);
  }

  @override
  TypeInformation visitUnresolvedSuperGetterCompound(
      ast.SendSet node,
      Element getter,
      SetterElement setter,
      op.AssignmentOperator operator,
      ast.Node rhs,
      _) {
    return handleSuperCompound(node, getter, setter, rhs);
  }

  @override
  TypeInformation visitUnresolvedSuperSetterCompound(
      ast.Send node,
      GetterElement getter,
      Element setter,
      op.AssignmentOperator operator,
      ast.Node rhs,
      _) {
    return handleSuperCompound(node, getter, setter, rhs);
  }

  @override
  TypeInformation visitSuperFieldFieldSetIfNull(ast.Send node,
      FieldElement readField, FieldElement writtenField, ast.Node rhs, _) {
    return handleSuperCompound(node, readField, writtenField, rhs);
  }

  @override
  TypeInformation visitSuperFieldSetIfNull(
      ast.Send node, FieldElement field, ast.Node rhs, _) {
    return handleSuperCompound(node, field, field, rhs);
  }

  @override
  TypeInformation visitSuperFieldSetterSetIfNull(ast.Send node,
      FieldElement field, SetterElement setter, ast.Node rhs, _) {
    return handleSuperCompound(node, field, setter, rhs);
  }

  @override
  TypeInformation visitSuperGetterFieldSetIfNull(ast.Send node,
      GetterElement getter, FieldElement field, ast.Node rhs, _) {
    return handleSuperCompound(node, getter, field, rhs);
  }

  @override
  TypeInformation visitSuperGetterSetterSetIfNull(ast.Send node,
      GetterElement getter, SetterElement setter, ast.Node rhs, _) {
    return handleSuperCompound(node, getter, setter, rhs);
  }

  @override
  TypeInformation visitSuperMethodSetIfNull(
      ast.Send node, FunctionElement method, ast.Node rhs, _) {
    return handleSuperCompound(node, method, null, rhs);
  }

  @override
  TypeInformation visitSuperMethodSetterSetIfNull(ast.Send node,
      FunctionElement method, SetterElement setter, ast.Node rhs, _) {
    return handleSuperCompound(node, method, setter, rhs);
  }

  TypeInformation handleSuperCompound(
      ast.SendSet node, Element getter, Element setter, ast.Node rhs) {
    TypeInformation rhsType = visit(rhs);
    return _handleSuperCompound(node, getter, setter, rhsType);
  }

  @override
  TypeInformation visitSuperFieldFieldPostfix(
      ast.SendSet node,
      FieldElement readField,
      FieldElement writtenField,
      op.IncDecOperator operator,
      _) {
    return handleSuperPrefixPostfix(node, readField, writtenField);
  }

  @override
  TypeInformation visitSuperFieldFieldPrefix(
      ast.SendSet node,
      FieldElement readField,
      FieldElement writtenField,
      op.IncDecOperator operator,
      _) {
    return handleSuperPrefixPostfix(node, readField, writtenField);
  }

  @override
  TypeInformation visitSuperFieldPostfix(
      ast.SendSet node, FieldElement field, op.IncDecOperator operator, _) {
    return handleSuperPrefixPostfix(node, field, field);
  }

  @override
  TypeInformation visitSuperFieldPrefix(
      ast.SendSet node, FieldElement field, op.IncDecOperator operator, _) {
    return handleSuperPrefixPostfix(node, field, field);
  }

  @override
  TypeInformation visitSuperFieldSetterPostfix(ast.SendSet node,
      FieldElement field, SetterElement setter, op.IncDecOperator operator, _) {
    return handleSuperPrefixPostfix(node, field, setter);
  }

  @override
  TypeInformation visitSuperFieldSetterPrefix(ast.SendSet node,
      FieldElement field, SetterElement setter, op.IncDecOperator operator, _) {
    return handleSuperPrefixPostfix(node, field, setter);
  }

  @override
  TypeInformation visitSuperGetterFieldPostfix(ast.SendSet node,
      GetterElement getter, FieldElement field, op.IncDecOperator operator, _) {
    return handleSuperPrefixPostfix(node, getter, field);
  }

  @override
  TypeInformation visitSuperGetterFieldPrefix(ast.SendSet node,
      GetterElement getter, FieldElement field, op.IncDecOperator operator, _) {
    return handleSuperPrefixPostfix(node, getter, field);
  }

  @override
  TypeInformation visitSuperGetterSetterPostfix(
      ast.SendSet node,
      GetterElement getter,
      SetterElement setter,
      op.IncDecOperator operator,
      _) {
    return handleSuperPrefixPostfix(node, getter, setter);
  }

  @override
  TypeInformation visitSuperGetterSetterPrefix(
      ast.SendSet node,
      GetterElement getter,
      SetterElement setter,
      op.IncDecOperator operator,
      _) {
    return handleSuperPrefixPostfix(node, getter, setter);
  }

  @override
  TypeInformation visitSuperMethodSetterPostfix(
      ast.SendSet node,
      FunctionElement method,
      SetterElement setter,
      op.IncDecOperator operator,
      _) {
    return handleSuperPrefixPostfix(node, method, setter);
  }

  @override
  TypeInformation visitSuperMethodSetterPrefix(
      ast.SendSet node,
      FunctionElement method,
      SetterElement setter,
      op.IncDecOperator operator,
      _) {
    return handleSuperPrefixPostfix(node, method, setter);
  }

  @override
  TypeInformation visitUnresolvedSuperPrefix(
      ast.SendSet node, Element element, op.IncDecOperator operator, _) {
    return handleSuperPrefixPostfix(node, element, element);
  }

  @override
  TypeInformation visitUnresolvedSuperPostfix(
      ast.SendSet node, Element element, op.IncDecOperator operator, _) {
    return handleSuperPrefixPostfix(node, element, element);
  }

  @override
  TypeInformation visitUnresolvedSuperGetterPrefix(ast.SendSet node,
      Element getter, SetterElement setter, op.IncDecOperator operator, _) {
    return handleSuperPrefixPostfix(node, getter, setter);
  }

  @override
  TypeInformation visitUnresolvedSuperGetterPostfix(ast.SendSet node,
      Element getter, SetterElement setter, op.IncDecOperator operator, _) {
    return handleSuperPrefixPostfix(node, getter, setter);
  }

  @override
  TypeInformation visitUnresolvedSuperSetterPrefix(ast.SendSet node,
      GetterElement getter, Element setter, op.IncDecOperator operator, _) {
    return handleSuperPrefixPostfix(node, getter, setter);
  }

  @override
  TypeInformation visitUnresolvedSuperSetterPostfix(ast.SendSet node,
      GetterElement getter, Element setter, op.IncDecOperator operator, _) {
    return handleSuperPrefixPostfix(node, getter, setter);
  }

  TypeInformation handleSuperPrefixPostfix(
      ast.SendSet node, Element getter, Element setter) {
    return _handleSuperCompound(node, getter, setter, types.uint31Type);
  }

  TypeInformation _handleSuperCompound(ast.SendSet node, Element getter,
      Element setter, TypeInformation rhsType) {
    Selector getterSelector = elements.getGetterSelectorInComplexSendSet(node);
    TypeMask getterMask = memberData.typeOfGetter(node);
    Selector setterSelector = elements.getSelector(node);
    TypeMask setterMask = memberData.typeOfSend(node);

    TypeInformation getterType =
        handleSuperSend(node, getterSelector, getterMask, getter, null);

    TypeInformation returnType;
    if (node.isIfNullAssignment) {
      returnType = types.allocateDiamondPhi(getterType, rhsType);
    } else {
      Selector operatorSelector =
          elements.getOperatorSelectorInComplexSendSet(node);
      TypeMask operatorMask = memberData.typeOfOperator(node);
      returnType = handleDynamicSend(CallType.complex, node, operatorSelector,
          operatorMask, getterType, new ArgumentsTypes([rhsType], null));
    }
    handleSuperSend(node, setterSelector, setterMask, setter,
        new ArgumentsTypes([returnType], null));

    return node.isPostfix ? getterType : returnType;
  }

  /// Handle index set, like `foo[0] = 42`.
  TypeInformation handleIndexSet(ast.SendSet node, TypeInformation receiverType,
      TypeInformation indexType, TypeInformation rhsType) {
    Selector setterSelector = elements.getSelector(node);
    TypeMask setterMask = memberData.typeOfSend(node);
    handleDynamicSend(CallType.complex, node, setterSelector, setterMask,
        receiverType, new ArgumentsTypes([indexType, rhsType], null));
    return rhsType;
  }

  @override
  TypeInformation visitIndexSet(
      ast.SendSet node, ast.Node receiver, ast.Node index, ast.Node rhs, _) {
    TypeInformation receiverType = visit(receiver);
    TypeInformation indexType = visit(index);
    TypeInformation rhsType = visit(rhs);
    return handleIndexSet(node, receiverType, indexType, rhsType);
  }

  /// Handle super index set, like `super[42] = true`.
  TypeInformation handleSuperIndexSet(
      ast.SendSet node, Element element, ast.Node index, ast.Node rhs) {
    TypeInformation indexType = visit(index);
    TypeInformation rhsType = visit(rhs);
    Selector setterSelector = elements.getSelector(node);
    TypeMask setterMask = memberData.typeOfSend(node);
    handleStaticSend(node, setterSelector, setterMask, element,
        new ArgumentsTypes([indexType, rhsType], null));
    return rhsType;
  }

  @override
  TypeInformation visitSuperIndexSet(ast.SendSet node, FunctionElement function,
      ast.Node index, ast.Node rhs, _) {
    return handleSuperIndexSet(node, function, index, rhs);
  }

  @override
  TypeInformation visitUnresolvedSuperIndexSet(ast.SendSet node,
      ErroneousElement element, ast.Node index, ast.Node rhs, _) {
    return handleSuperIndexSet(node, element, index, rhs);
  }

  TypeInformation handlePlainAssignment(
      ast.Node node,
      Element element,
      Selector setterSelector,
      TypeMask setterMask,
      TypeInformation receiverType,
      TypeInformation rhsType,
      ast.Node rhs) {
    ArgumentsTypes arguments = new ArgumentsTypes([rhsType], null);
    if (Elements.isMalformed(element)) {
      // Code will always throw.
    } else if (Elements.isStaticOrTopLevelField(element)) {
      handleStaticSend(node, setterSelector, setterMask, element, arguments);
    } else if (Elements.isUnresolved(element) || element.isSetter) {
      if (analyzedElement.isGenerativeConstructor &&
          (node.asSendSet() != null) &&
          (node.asSendSet().receiver != null) &&
          node.asSendSet().receiver.isThis()) {
        Iterable<MemberEntity> targets = closedWorld.locateMembers(
            setterSelector, types.newTypedSelector(thisType, setterMask));
        // We just recognized a field initialization of the form:
        // `this.foo = 42`. If there is only one target, we can update
        // its type.
        if (targets.length == 1) {
          MemberElement single = targets.first;
          if (single.isField) {
            FieldElement field = single;
            locals.updateField(field, rhsType);
          }
        }
      }
      handleDynamicSend(CallType.access, node, setterSelector, setterMask,
          receiverType, arguments);
    } else if (element.isField) {
      FieldElement field = element;
      if (field.isFinal) {
        inferrer.recordTypeOfField(field, rhsType);
      } else {
        if (analyzedElement.isGenerativeConstructor) {
          locals.updateField(field, rhsType);
        }
        if (visitingInitializers) {
          inferrer.recordTypeOfField(field, rhsType);
        } else {
          handleDynamicSend(CallType.complex, node, setterSelector, setterMask,
              receiverType, arguments);
        }
      }
    } else if (element.isLocal) {
      LocalElement local = element;
      ast.SendSet sendSet = node.asSendSet();
      bool isSetIfNull = sendSet != null && sendSet.isIfNullAssignment;
      locals.update(local, rhsType, node, local.type, isSetIfNull: isSetIfNull);
    }
    return rhsType;
  }

  /// Handle a super access or invocation that results in a `noSuchMethod` call.
  TypeInformation handleErroneousSuperSend(ast.Send node) {
    ArgumentsTypes arguments =
        node.isPropertyAccess ? null : analyzeArguments(node.arguments);
    Selector selector = elements.getSelector(node);
    TypeMask mask = memberData.typeOfSend(node);
    // TODO(herhut): We could do better here if we knew what we
    // are calling does not expose this.
    // TODO(johnniwinther): Do we still need this when calling directly?
    isThisExposed = true;
    return handleSuperNoSuchMethod(node, selector, mask, arguments);
  }

  TypeInformation handleSuperNoSuchMethod(ast.Send node, Selector selector,
      TypeMask mask, ArgumentsTypes arguments) {
    // Ensure we create a node, to make explicit the call to the
    // `noSuchMethod` handler.
    ClassElement cls = outermostElement.enclosingClass;
    MethodElement element = cls.lookupSuperMember(Identifiers.noSuchMethod_);
    if (!Selectors.noSuchMethod_.signatureApplies(element)) {
      ClassElement objectClass = closedWorld.commonElements.objectClass;
      element = objectClass.lookupMember(Identifiers.noSuchMethod_);
    }
    return handleStaticSend(node, selector, mask, element, arguments);
  }

  /// Handle a .call invocation on the values retrieved from the super
  /// [element]. For instance `super.foo(bar)` where `foo` is a field or getter.
  TypeInformation handleSuperClosureCall(
      ast.Send node, MemberElement element, ast.NodeList arguments) {
    ArgumentsTypes argumentTypes = analyzeArguments(arguments.nodes);
    Selector selector = elements.getSelector(node);
    TypeMask mask = memberData.typeOfSend(node);
    // TODO(herhut): We could do better here if we knew what we
    // are calling does not expose this.
    isThisExposed = true;
    return inferrer.registerCalledClosure(
        node,
        selector,
        mask,
        inferrer.typeOfMember(element),
        outermostElement,
        argumentTypes,
        sideEffectsBuilder,
        inLoop: inLoop);
  }

  /// Handle an invocation of super [method].
  TypeInformation handleSuperMethodInvoke(
      ast.Send node, MethodElement method, ArgumentsTypes arguments) {
    // TODO(herhut): We could do better here if we knew what we
    // are calling does not expose this.
    isThisExposed = true;
    Selector selector = elements.getSelector(node);
    TypeMask mask = memberData.typeOfSend(node);
    return handleStaticSend(node, selector, mask, method, arguments);
  }

  /// Handle access to a super field or getter [element].
  TypeInformation handleSuperGet(ast.Send node, Element element) {
    // TODO(herhut): We could do better here if we knew what we
    // are calling does not expose this.
    isThisExposed = true;
    Selector selector = elements.getSelector(node);
    TypeMask mask = memberData.typeOfSend(node);
    return handleStaticSend(node, selector, mask, element, null);
  }

  /// Handle update to a super field or setter [element].
  TypeInformation handleSuperSet(ast.Send node, Element element, ast.Node rhs) {
    TypeInformation rhsType = visit(rhs);
    // TODO(herhut): We could do better here if we knew what we
    // are calling does not expose this.
    isThisExposed = true;
    Selector selector = elements.getSelector(node);
    TypeMask mask = memberData.typeOfSend(node);
    handleStaticSend(
        node, selector, mask, element, new ArgumentsTypes([rhsType], null));
    return rhsType;
  }

  @override
  TypeInformation visitSuperFieldSet(
      ast.Send node, FieldElement method, ast.Node rhs, _) {
    return handleSuperSet(node, method, rhs);
  }

  @override
  TypeInformation visitSuperSetterSet(
      ast.SendSet node, SetterElement field, ast.Node rhs, _) {
    return handleSuperSet(node, field, rhs);
  }

  @override
  TypeInformation visitUnresolvedSuperIndex(
      ast.Send node, Element element, ast.Node index, _) {
    return handleErroneousSuperSend(node);
  }

  @override
  TypeInformation visitUnresolvedSuperUnary(
      ast.Send node, op.UnaryOperator operator, Element element, _) {
    return handleErroneousSuperSend(node);
  }

  @override
  TypeInformation visitUnresolvedSuperBinary(ast.Send node, Element element,
      op.BinaryOperator operator, ast.Node argument, _) {
    return handleErroneousSuperSend(node);
  }

  @override
  TypeInformation visitUnresolvedSuperGet(ast.Send node, Element element, _) {
    return handleErroneousSuperSend(node);
  }

  @override
  TypeInformation visitSuperSetterGet(ast.Send node, MethodElement setter, _) {
    return handleErroneousSuperSend(node);
  }

  @override
  TypeInformation visitSuperGetterSet(
      ast.Send node, GetterElement getter, ast.Node rhs, _) {
    return handleErroneousSuperSend(node);
  }

  @override
  TypeInformation visitSuperMethodSet(
      ast.SendSet node, MethodElement method, ast.Node rhs, _) {
    return handleErroneousSuperSend(node);
  }

  @override
  TypeInformation visitFinalSuperFieldSet(
      ast.Send node, FieldElement method, ast.Node rhs, _) {
    return handleErroneousSuperSend(node);
  }

  @override
  TypeInformation visitUnresolvedSuperSet(
      ast.Send node, Element element, ast.Node rhs, _) {
    return handleErroneousSuperSend(node);
  }

  @override
  TypeInformation visitUnresolvedSuperInvoke(
      ast.Send node, Element element, ast.Node argument, Selector selector, _) {
    return handleErroneousSuperSend(node);
  }

  @override
  TypeInformation visitSuperFieldGet(ast.Send node, FieldElement field, _) {
    return handleSuperGet(node, field);
  }

  @override
  TypeInformation visitSuperGetterGet(ast.Send node, MethodElement method, _) {
    return handleSuperGet(node, method);
  }

  @override
  TypeInformation visitSuperMethodGet(ast.Send node, MethodElement method, _) {
    return handleSuperGet(node, method);
  }

  @override
  TypeInformation visitSuperFieldInvoke(ast.Send node, FieldElement field,
      ast.NodeList arguments, CallStructure callStructure, _) {
    return handleSuperClosureCall(node, field, arguments);
  }

  @override
  TypeInformation visitSuperGetterInvoke(ast.Send node, GetterElement getter,
      ast.NodeList arguments, CallStructure callStructure, _) {
    return handleSuperClosureCall(node, getter, arguments);
  }

  @override
  TypeInformation visitSuperMethodInvoke(ast.Send node, MethodElement method,
      ast.NodeList arguments, CallStructure callStructure, _) {
    return handleSuperMethodInvoke(
        node, method, analyzeArguments(arguments.nodes));
  }

  @override
  TypeInformation visitSuperSetterInvoke(ast.Send node, SetterElement setter,
      ast.NodeList arguments, CallStructure callStructure, _) {
    return handleErroneousSuperSend(node);
  }

  @override
  TypeInformation visitSuperIndex(
      ast.Send node, MethodElement method, ast.Node index, _) {
    return handleSuperMethodInvoke(
        node, method, analyzeArguments(node.arguments));
  }

  @override
  TypeInformation visitSuperEquals(
      ast.Send node, MethodElement method, ast.Node argument, _) {
    // TODO(johnniwinther): Special case ==.
    return handleSuperMethodInvoke(
        node, method, analyzeArguments(node.arguments));
  }

  @override
  TypeInformation visitSuperNotEquals(
      ast.Send node, MethodElement method, ast.Node argument, _) {
    // TODO(johnniwinther): Special case !=.
    return handleSuperMethodInvoke(
        node, method, analyzeArguments(node.arguments));
  }

  @override
  TypeInformation visitSuperBinary(ast.Send node, MethodElement method,
      op.BinaryOperator operator, ast.Node argument, _) {
    return handleSuperMethodInvoke(
        node, method, analyzeArguments(node.arguments));
  }

  @override
  TypeInformation visitSuperUnary(
      ast.Send node, op.UnaryOperator operator, MethodElement method, _) {
    return handleSuperMethodInvoke(
        node, method, analyzeArguments(node.arguments));
  }

  @override
  TypeInformation visitSuperMethodIncompatibleInvoke(
      ast.Send node,
      MethodElement method,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    return handleErroneousSuperSend(node);
  }

  // Try to find the length given to a fixed array constructor call.
  int findLength(ast.Send node) {
    ast.Node firstArgument = node.arguments.head;
    Element element = elements[firstArgument];
    ast.LiteralInt length = firstArgument.asLiteralInt();
    if (length != null) {
      return length.value;
    } else if (element != null &&
        element.isField &&
        Elements.isStaticOrTopLevelField(element)) {
      FieldElement fieldElement = element;
      if (closedWorld.fieldNeverChanges(fieldElement)) {
        ConstantValue value =
            compiler.backend.constants.getConstantValue(fieldElement.constant);
        if (value != null && value.isInt) {
          IntConstantValue intValue = value;
          return intValue.primitiveValue;
        }
      }
    }
    return null;
  }

  TypeInformation visitAwait(ast.Await node) {
    TypeInformation futureType = node.expression.accept(this);
    return inferrer.registerAwait(node, futureType);
  }

  TypeInformation visitYield(ast.Yield node) {
    TypeInformation operandType = node.expression.accept(this);
    return inferrer.registerYield(node, operandType);
  }

  TypeInformation handleTypeLiteralInvoke(ast.NodeList arguments) {
    // This is reached when users forget to put a `new` in front of a type
    // literal. The emitter will generate an actual call (even though it is
    // likely invalid), and for that it needs to have the arguments processed
    // as well.
    analyzeArguments(arguments.nodes);
    return types.dynamicType;
  }

  /// Handle constructor invocation of [constructor].
  TypeInformation handleConstructorSend(
      ast.Send node, ConstructorElement constructor) {
    ConstructorElement target = constructor.implementation;
    ArgumentsTypes arguments = analyzeArguments(node.arguments);
    if (visitingInitializers) {
      if (ast.Initializers.isConstructorRedirect(node)) {
        isConstructorRedirect = true;
      } else if (ast.Initializers.isSuperConstructorCall(node)) {
        seenSuperConstructorCall = true;
        analyzeSuperConstructorCall(constructor);
      }
    }
    // If we are looking at a new expression on a forwarding factory, we have to
    // forward the call to the effective target of the factory.
    // TODO(herhut): Remove the loop once effectiveTarget forwards to patches.
    while (target.isFactoryConstructor) {
      if (!target.isRedirectingFactory) break;
      target = target.effectiveTarget.implementation;
    }
    if (closedWorld.commonElements.isForeign(target)) {
      return handleForeignSend(node, target);
    }
    Selector selector = elements.getSelector(node);
    CallStructure callStructure = selector.callStructure;
    TypeMask mask = memberData.typeOfSend(node);
    // In erroneous code the number of arguments in the selector might not
    // match the function element.
    // TODO(polux): return nonNullEmpty and check it doesn't break anything
    if (target.isMalformed ||
        !callStructure.signatureApplies(target.parameterStructure)) {
      return types.dynamicType;
    }

    TypeInformation returnType =
        handleStaticSend(node, selector, mask, target.declaration, arguments);
    if (Elements.isGrowableListConstructorCall(
        constructor, node, closedWorld.commonElements)) {
      return inferrer.concreteTypes.putIfAbsent(
          node,
          () => types.allocateList(types.growableListType, node,
              outermostElement, types.nonNullEmpty(), 0));
    } else if (Elements.isFixedListConstructorCall(
            constructor, node, closedWorld.commonElements) ||
        Elements.isFilledListConstructorCall(
            constructor, node, closedWorld.commonElements)) {
      int length = findLength(node);
      TypeInformation elementType = Elements.isFixedListConstructorCall(
              constructor, node, closedWorld.commonElements)
          ? types.nullType
          : arguments.positional[1];

      return inferrer.concreteTypes.putIfAbsent(
          node,
          () => types.allocateList(types.fixedListType, node, outermostElement,
              elementType, length));
    } else if (Elements.isConstructorOfTypedArraySubclass(
        constructor, closedWorld)) {
      int length = findLength(node);
      MemberElement member = target.enclosingClass.lookupMember('[]');
      TypeInformation elementType = inferrer.returnTypeOfMember(member);
      return inferrer.concreteTypes.putIfAbsent(
          node,
          () => types.allocateList(types.nonNullExact(target.enclosingClass),
              node, outermostElement, elementType, length));
    } else {
      return returnType;
    }
  }

  @override
  TypeInformation bulkHandleNew(ast.NewExpression node, _) {
    Element element = elements[node.send];
    return handleConstructorSend(node.send, element);
  }

  @override
  TypeInformation errorNonConstantConstructorInvoke(
      ast.NewExpression node,
      Element element,
      ResolutionDartType type,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    return bulkHandleNew(node, _);
  }

  /// Handle invocation of a top level or static field or getter [element].
  TypeInformation handleStaticFieldOrGetterInvoke(
      ast.Send node, MemberElement element) {
    ArgumentsTypes arguments = analyzeArguments(node.arguments);
    Selector selector = elements.getSelector(node);
    TypeMask mask = memberData.typeOfSend(node);
    handleStaticSend(node, selector, mask, element, arguments);
    return inferrer.registerCalledClosure(
        node,
        selector,
        mask,
        inferrer.typeOfMember(element),
        outermostElement,
        arguments,
        sideEffectsBuilder,
        inLoop: inLoop);
  }

  /// Handle invocation of a top level or static [function].
  TypeInformation handleStaticFunctionInvoke(
      ast.Send node, MethodElement function) {
    if (closedWorld.commonElements.isForeign(function)) {
      return handleForeignSend(node, function);
    }
    ArgumentsTypes arguments = analyzeArguments(node.arguments);
    Selector selector = elements.getSelector(node);
    TypeMask mask = memberData.typeOfSend(node);
    return handleStaticSend(node, selector, mask, function, arguments);
  }

  /// Handle an static invocation of an unresolved target or with incompatible
  /// arguments to a resolved target.
  TypeInformation handleInvalidStaticInvoke(ast.Send node) {
    analyzeArguments(node.arguments);
    return types.dynamicType;
  }

  @override
  TypeInformation visitStaticFieldInvoke(ast.Send node, FieldElement field,
      ast.NodeList arguments, CallStructure callStructure, _) {
    return handleStaticFieldOrGetterInvoke(node, field);
  }

  @override
  TypeInformation visitStaticFunctionInvoke(
      ast.Send node,
      MethodElement function,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    return handleStaticFunctionInvoke(node, function);
  }

  @override
  TypeInformation visitStaticFunctionIncompatibleInvoke(
      ast.Send node,
      MethodElement function,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    return handleInvalidStaticInvoke(node);
  }

  @override
  TypeInformation visitStaticGetterInvoke(ast.Send node, GetterElement getter,
      ast.NodeList arguments, CallStructure callStructure, _) {
    return handleStaticFieldOrGetterInvoke(node, getter);
  }

  @override
  TypeInformation visitTopLevelFieldInvoke(ast.Send node, FieldElement field,
      ast.NodeList arguments, CallStructure callStructure, _) {
    return handleStaticFieldOrGetterInvoke(node, field);
  }

  @override
  TypeInformation visitTopLevelFunctionInvoke(
      ast.Send node,
      MethodElement function,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    return handleStaticFunctionInvoke(node, function);
  }

  @override
  TypeInformation visitTopLevelFunctionIncompatibleInvoke(
      ast.Send node,
      MethodElement function,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    return handleInvalidStaticInvoke(node);
  }

  @override
  TypeInformation visitTopLevelGetterInvoke(ast.Send node, GetterElement getter,
      ast.NodeList arguments, CallStructure callStructure, _) {
    return handleStaticFieldOrGetterInvoke(node, getter);
  }

  @override
  TypeInformation visitStaticSetterInvoke(ast.Send node, MethodElement setter,
      ast.NodeList arguments, CallStructure callStructure, _) {
    return handleInvalidStaticInvoke(node);
  }

  @override
  TypeInformation visitTopLevelSetterInvoke(ast.Send node, MethodElement setter,
      ast.NodeList arguments, CallStructure callStructure, _) {
    return handleInvalidStaticInvoke(node);
  }

  @override
  TypeInformation visitUnresolvedInvoke(ast.Send node, Element element,
      ast.NodeList arguments, Selector selector, _) {
    return handleInvalidStaticInvoke(node);
  }

  TypeInformation handleForeignSend(ast.Send node, Element element) {
    ArgumentsTypes arguments = analyzeArguments(node.arguments);
    Selector selector = elements.getSelector(node);
    TypeMask mask = memberData.typeOfSend(node);
    String name = element.name;
    handleStaticSend(node, selector, mask, element, arguments);
    if (name == JavaScriptBackend.JS ||
        name == JavaScriptBackend.JS_EMBEDDED_GLOBAL ||
        name == JavaScriptBackend.JS_BUILTIN) {
      native.NativeBehavior nativeBehavior = elements.getNativeData(node);
      sideEffectsBuilder.add(nativeBehavior.sideEffects);
      return inferrer.typeOfNativeBehavior(nativeBehavior);
    } else if (name == JavaScriptBackend.JS_STRING_CONCAT) {
      return types.stringType;
    } else {
      sideEffectsBuilder.setAllSideEffects();
      return types.dynamicType;
    }
  }

  ArgumentsTypes analyzeArguments(Link<ast.Node> arguments) {
    List positional = [];
    Map<String, TypeInformation> named;
    for (var argument in arguments) {
      ast.NamedArgument namedArgument = argument.asNamedArgument();
      if (namedArgument != null) {
        argument = namedArgument.expression;
        if (named == null) named = new Map<String, TypeInformation>();
        named[namedArgument.name.source] = argument.accept(this);
      } else {
        positional.add(argument.accept(this));
      }
      // TODO(ngeoffray): We could do better here if we knew what we
      // are calling does not expose this.
      isThisExposed = isThisExposed || argument.isThis();
    }
    return new ArgumentsTypes(positional, named);
  }

  /// Read a local variable, function or parameter.
  TypeInformation handleLocalGet(ast.Send node, LocalElement local) {
    assert(locals.use(local) != null);
    return locals.use(local);
  }

  /// Read a static or top level field.
  TypeInformation handleStaticFieldGet(ast.Send node, FieldElement field) {
    Selector selector = elements.getSelector(node);
    TypeMask mask = memberData.typeOfSend(node);
    return handleStaticSend(node, selector, mask, field, null);
  }

  /// Invoke a static or top level getter.
  TypeInformation handleStaticGetterGet(ast.Send node, GetterElement getter) {
    Selector selector = elements.getSelector(node);
    TypeMask mask = memberData.typeOfSend(node);
    return handleStaticSend(node, selector, mask, getter, null);
  }

  /// Closurize a static or top level function.
  TypeInformation handleStaticFunctionGet(
      ast.Send node, MethodElement function) {
    Selector selector = elements.getSelector(node);
    TypeMask mask = memberData.typeOfSend(node);
    return handleStaticSend(node, selector, mask, function, null);
  }

  @override
  TypeInformation visitDynamicPropertyGet(
      ast.Send node, ast.Node receiver, Name name, _) {
    return handleDynamicGet(node);
  }

  @override
  TypeInformation visitIfNotNullDynamicPropertyGet(
      ast.Send node, ast.Node receiver, Name name, _) {
    return handleDynamicGet(node);
  }

  @override
  TypeInformation visitLocalVariableGet(
      ast.Send node, LocalVariableElement variable, _) {
    return handleLocalGet(node, variable);
  }

  @override
  TypeInformation visitParameterGet(
      ast.Send node, ParameterElement parameter, _) {
    return handleLocalGet(node, parameter);
  }

  @override
  TypeInformation visitLocalFunctionGet(
      ast.Send node, LocalFunctionElement function, _) {
    return handleLocalGet(node, function);
  }

  @override
  TypeInformation visitStaticFieldGet(ast.Send node, FieldElement field, _) {
    return handleStaticFieldGet(node, field);
  }

  @override
  TypeInformation visitStaticFunctionGet(
      ast.Send node, MethodElement function, _) {
    return handleStaticFunctionGet(node, function);
  }

  @override
  TypeInformation visitStaticGetterGet(ast.Send node, GetterElement getter, _) {
    return handleStaticGetterGet(node, getter);
  }

  @override
  TypeInformation visitThisPropertyGet(ast.Send node, Name name, _) {
    return handleDynamicGet(node);
  }

  @override
  TypeInformation visitTopLevelFieldGet(ast.Send node, FieldElement field, _) {
    return handleStaticFieldGet(node, field);
  }

  @override
  TypeInformation visitTopLevelFunctionGet(
      ast.Send node, MethodElement function, _) {
    return handleStaticFunctionGet(node, function);
  }

  @override
  TypeInformation visitTopLevelGetterGet(
      ast.Send node, GetterElement getter, _) {
    return handleStaticGetterGet(node, getter);
  }

  @override
  TypeInformation visitStaticSetterGet(ast.Send node, MethodElement setter, _) {
    return types.dynamicType;
  }

  @override
  TypeInformation visitTopLevelSetterGet(
      ast.Send node, MethodElement setter, _) {
    return types.dynamicType;
  }

  @override
  TypeInformation visitUnresolvedGet(ast.Send node, Element element, _) {
    return types.dynamicType;
  }

  /// Handle .call invocation on [closure].
  TypeInformation handleCallInvoke(ast.Send node, TypeInformation closure) {
    ArgumentsTypes arguments = analyzeArguments(node.arguments);
    Selector selector = elements.getSelector(node);
    TypeMask mask = memberData.typeOfSend(node);
    return handleDynamicSend(
        CallType.access, node, selector, mask, closure, arguments);
  }

  @override
  TypeInformation visitExpressionInvoke(ast.Send node, ast.Node expression,
      ast.NodeList arguments, CallStructure callStructure, _) {
    return handleCallInvoke(node, expression.accept(this));
  }

  @override
  TypeInformation visitThisInvoke(
      ast.Send node, ast.NodeList arguments, CallStructure callStructure, _) {
    return handleCallInvoke(node, thisType);
  }

  @override
  TypeInformation visitParameterInvoke(
      ast.Send node,
      ParameterElement parameter,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    return handleCallInvoke(node, locals.use(parameter));
  }

  @override
  TypeInformation visitLocalVariableInvoke(
      ast.Send node,
      LocalVariableElement variable,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    return handleCallInvoke(node, locals.use(variable));
  }

  @override
  TypeInformation visitLocalFunctionInvoke(
      ast.Send node,
      LocalFunctionElement function,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    ArgumentsTypes argumentTypes = analyzeArguments(node.arguments);
    Selector selector = elements.getSelector(node);
    TypeMask mask = memberData.typeOfSend(node);
    // This only works for function statements. We need a
    // more sophisticated type system with function types to support
    // more.
    return inferrer.registerCalledMember(node, selector, mask, outermostElement,
        function.callMethod, argumentTypes, sideEffectsBuilder, inLoop);
  }

  @override
  TypeInformation visitLocalFunctionIncompatibleInvoke(
      ast.Send node,
      LocalFunctionElement function,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    analyzeArguments(node.arguments);
    return types.dynamicType;
  }

  TypeInformation handleStaticSend(ast.Node node, Selector selector,
      TypeMask mask, MemberElement element, ArgumentsTypes arguments) {
    assert(element.isDeclaration);
    assert(!element.isFactoryConstructor ||
        !(element as ConstructorElement).isRedirectingFactory);
    // Erroneous elements may be unresolved, for example missing getters.
    if (Elements.isUnresolved(element)) return types.dynamicType;
    // TODO(herhut): should we follow redirecting constructors here? We would
    // need to pay attention if the constructor is pointing to an erroneous
    // element.
    return inferrer.registerCalledMember(node, selector, mask, outermostElement,
        element, arguments, sideEffectsBuilder, inLoop);
  }

  TypeInformation handleDynamicSend(
      CallType callType,
      ast.Node node,
      Selector selector,
      TypeMask mask,
      TypeInformation receiverType,
      ArgumentsTypes arguments) {
    assert(receiverType != null);
    if (types.selectorNeedsUpdate(receiverType, mask)) {
      mask = receiverType == types.dynamicType
          ? null
          : types.newTypedSelector(receiverType, mask);
      inferrer.updateSelectorInMember(
          outermostElement, callType, node, selector, mask);
    }

    // If the receiver of the call is a local, we may know more about
    // its type by refining it with the potential targets of the
    // calls.
    ast.Send send = node.asSend();
    bool isConditional = false;
    if (send != null) {
      isConditional = send.isConditional;
      ast.Send receiver = send.receiver?.asSend();
      Element element;
      if (receiver != null && receiver.isPropertyAccess) {
        // We have `local.method()` || `local?.method()`.
        element = elements[receiver];
      } else if (send.receiver == null) {
        // We have `local()`.
        element = elements[send];
      }
      if (Elements.isLocal(element) && !capturedVariables.contains(element)) {
        TypeInformation refinedType = types.refineReceiver(
            selector, mask, receiverType,
            isConditional: send.isConditional);
        LocalElement local = element;
        locals.update(local, refinedType, node, local.type);
      }
      // TODO(johnniwinther): Enable this to improve precision of conditional
      // access. This cannot currently be done because the receiver and the
      // call shares type mask.
      /*if (isConditional) {
      receiverType = types.narrowNotNull(receiverType);
      }*/
    }

    return inferrer.registerCalledSelector(callType, node, selector, mask,
        receiverType, outermostElement, arguments, sideEffectsBuilder,
        inLoop: inLoop, isConditional: isConditional);
  }

  TypeInformation handleDynamicInvoke(ast.Send node) {
    return _handleDynamicSend(node);
  }

  TypeInformation handleDynamicGet(ast.Send node) {
    return _handleDynamicSend(node);
  }

  TypeInformation _handleDynamicSend(ast.Send node) {
    Element element = elements[node];
    TypeInformation receiverType;
    bool isCallOnThis = false;
    if (node.receiver == null) {
      if (treatAsInstanceMember(element)) {
        isCallOnThis = true;
        receiverType = thisType;
      }
    } else {
      ast.Node receiver = node.receiver;
      isCallOnThis = isThisOrSuper(receiver);
      receiverType = visit(receiver);
    }

    Selector selector = elements.getSelector(node);
    TypeMask mask = memberData.typeOfSend(node);
    if (!isThisExposed && isCallOnThis) {
      checkIfExposesThis(selector, types.newTypedSelector(receiverType, mask));
    }

    ArgumentsTypes arguments =
        node.isPropertyAccess ? null : analyzeArguments(node.arguments);
    if (selector.name == '==' || selector.name == '!=') {
      if (types.isNull(receiverType)) {
        potentiallyAddNullCheck(node, node.arguments.head);
        return types.boolType;
      } else if (types.isNull(arguments.positional[0])) {
        potentiallyAddNullCheck(node, node.receiver);
        return types.boolType;
      }
    }
    return handleDynamicSend(
        CallType.access, node, selector, mask, receiverType, arguments);
  }

  void recordReturnType(TypeInformation type) {
    MethodElement analyzedMethod = analyzedElement;
    returnType =
        inferrer.addReturnTypeForMethod(analyzedMethod, returnType, type);
  }

  TypeInformation synthesizeForwardingCall(
      Spannable node, ConstructorElement element) {
    assert(element.isDeclaration);
    MethodElement function = analyzedElement.implementation;
    FunctionSignature signature = function.functionSignature;
    FunctionSignature calleeSignature = element.functionSignature;
    if (!calleeSignature.isCompatibleWith(signature)) {
      return types.nonNullEmpty();
    }

    List<TypeInformation> unnamed = <TypeInformation>[];
    signature.forEachRequiredParameter((FormalElement _element) {
      ParameterElement element = _element;
      assert(locals.use(element) != null);
      unnamed.add(locals.use(element));
    });

    Map<String, TypeInformation> named;
    if (signature.optionalParametersAreNamed) {
      named = new Map<String, TypeInformation>();
      signature.forEachOptionalParameter((FormalElement _element) {
        ParameterElement element = _element;
        named[element.name] = locals.use(element);
      });
    } else {
      signature.forEachOptionalParameter((FormalElement _element) {
        ParameterElement element = _element;
        unnamed.add(locals.use(element));
      });
    }

    ArgumentsTypes arguments = new ArgumentsTypes(unnamed, named);
    return inferrer.registerCalledMember(node, null, null, outermostElement,
        element, arguments, sideEffectsBuilder, inLoop);
  }

  TypeInformation visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) {
    ConstructorElement element = elements.getRedirectingTargetConstructor(node);
    if (Elements.isMalformed(element)) {
      recordReturnType(types.dynamicType);
    } else {
      // We don't create a selector for redirecting factories, and
      // the send is just a property access. Therefore we must
      // manually create the [ArgumentsTypes] of the call, and
      // manually register [analyzedElement] as a caller of [element].
      TypeInformation mask =
          synthesizeForwardingCall(node.constructorReference, element);
      recordReturnType(mask);
    }
    locals.seenReturnOrThrow = true;
    return null;
  }

  TypeInformation visitReturn(ast.Return node) {
    ast.Node expression = node.expression;
    recordReturnType(
        expression == null ? types.nullType : expression.accept(this));
    locals.seenReturnOrThrow = true;
    initializationIsIndefinite();
    return null;
  }

  TypeInformation handleForInLoop(
      ast.ForIn node,
      TypeInformation iteratorType,
      Selector currentSelector,
      TypeMask currentMask,
      Selector moveNextSelector,
      TypeMask moveNextMask) {
    handleDynamicSend(CallType.forIn, node, moveNextSelector, moveNextMask,
        iteratorType, new ArgumentsTypes.empty());
    TypeInformation currentType = handleDynamicSend(CallType.forIn, node,
        currentSelector, currentMask, iteratorType, new ArgumentsTypes.empty());

    if (node.expression.isThis()) {
      // Any reasonable implementation of an iterator would expose
      // this, so we play it safe and assume it will.
      isThisExposed = true;
    }

    ast.Node identifier = node.declaredIdentifier;
    Element element = elements.getForInVariable(node);
    Selector selector = elements.getSelector(identifier);
    TypeMask mask = memberData.typeOfSend(identifier.asSend());

    TypeInformation receiverType;
    if (element != null && element.isInstanceMember) {
      receiverType = thisType;
    } else {
      receiverType = types.dynamicType;
    }

    handlePlainAssignment(identifier, element, selector, mask, receiverType,
        currentType, node.expression);
    return handleLoop(node, () {
      visit(node.body);
    });
  }

  TypeInformation visitAsyncForIn(ast.AsyncForIn node) {
    TypeInformation expressionType = visit(node.expression);

    Selector currentSelector = Selectors.current;
    TypeMask currentMask = memberData.typeOfIteratorCurrent(node);
    Selector moveNextSelector = Selectors.moveNext;
    TypeMask moveNextMask = memberData.typeOfIteratorMoveNext(node);

    ConstructorElement ctor =
        closedWorld.commonElements.streamIteratorConstructor;

    /// Synthesize a call to the [StreamIterator] constructor.
    TypeInformation iteratorType = handleStaticSend(
        node, null, null, ctor, new ArgumentsTypes([expressionType], null));

    return handleForInLoop(node, iteratorType, currentSelector, currentMask,
        moveNextSelector, moveNextMask);
  }

  TypeInformation visitSyncForIn(ast.SyncForIn node) {
    TypeInformation expressionType = visit(node.expression);
    Selector iteratorSelector = Selectors.iterator;
    TypeMask iteratorMask = memberData.typeOfIterator(node);
    Selector currentSelector = Selectors.current;
    TypeMask currentMask = memberData.typeOfIteratorCurrent(node);
    Selector moveNextSelector = Selectors.moveNext;
    TypeMask moveNextMask = memberData.typeOfIteratorMoveNext(node);

    TypeInformation iteratorType = handleDynamicSend(
        CallType.forIn,
        node,
        iteratorSelector,
        iteratorMask,
        expressionType,
        new ArgumentsTypes.empty());

    return handleForInLoop(node, iteratorType, currentSelector, currentMask,
        moveNextSelector, moveNextMask);
  }
}
