// Copyright (c) 2017, 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.

import 'package:kernel/ast.dart' as ir;

import '../closure.dart';
import '../common.dart';
import '../common/names.dart';
import '../constants/constant_system.dart' as constant_system;
import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/jumps.dart';
import '../elements/types.dart';
import '../inferrer/abstract_value_domain.dart';
import '../inferrer/types.dart';
import '../ir/constants.dart';
import '../ir/static_type_provider.dart';
import '../ir/util.dart';
import '../js_backend/field_analysis.dart';
import '../js_model/element_map.dart';
import '../js_model/locals.dart' show JumpVisitor;
import '../js_model/js_world.dart';
import '../native/behavior.dart';
import '../options.dart';
import '../universe/selector.dart';
import '../universe/side_effects.dart';
import '../util/util.dart';
import 'inferrer_engine.dart';
import 'locals_handler.dart';
import 'type_graph_nodes.dart';
import 'type_system.dart';

/// [KernelTypeGraphBuilder] constructs a type-inference graph for a particular
/// element.
///
/// Calling [run] will start the work of visiting the body of the code to
/// construct a set of inference-nodes that abstractly represent what the code
/// is doing.
class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation>
    with ir.VisitorNullMixin<TypeInformation> {
  final CompilerOptions _options;
  final JsClosedWorld _closedWorld;
  final InferrerEngine _inferrer;
  final TypeSystem _types;
  final MemberEntity _analyzedMember;
  final ir.Node _analyzedNode;
  final KernelToLocalsMap _localsMap;
  final GlobalTypeInferenceElementData _memberData;
  final bool _inGenerativeConstructor;

  DartTypes get _dartTypes => _closedWorld.dartTypes;

  LocalState _stateInternal;
  LocalState _stateAfterWhenTrueInternal;
  LocalState _stateAfterWhenFalseInternal;

  /// Returns the current local state for when the boolean value of the most
  /// recently visited node is not taken into account
  LocalState get _state {
    return _stateInternal;
  }

  /// Sets the current local state for when the boolean value of the most
  /// recently visited node is not taken into account
  ///
  /// This used for when the most recently visited node is not a boolean
  /// expression and there for also resets [_stateAfterWhenTrue] and
  /// [_stateAfterWhenFalse] to the same value.
  void set _state(LocalState value) {
    _stateInternal = value;
    _stateAfterWhenTrueInternal = _stateAfterWhenFalseInternal = null;
  }

  /// Returns the current local state for when the most recently visited node
  /// has evaluated to `true`.
  ///
  /// If the most recently visited node is not a boolean expression then this is
  /// the same as [_state].
  LocalState get _stateAfterWhenTrue =>
      _stateAfterWhenTrueInternal ?? _stateInternal;

  /// Returns the current local state for when the most recently visited node
  /// has evaluated to `false`.
  ///
  /// If the most recently visited node is not a boolean expression then this is
  /// the same as [_state].
  LocalState get _stateAfterWhenFalse =>
      _stateAfterWhenFalseInternal ?? _stateInternal;

  /// Sets the current local state. [base] is the local state for when the
  /// boolean value of the most recently visited node is not taken into account.
  /// [whenTrue] and [whenFalse] are the local state for when the boolean value
  /// of the most recently visited node is `true` or `false`, respectively.
  void _setStateAfter(
      LocalState base, LocalState whenTrue, LocalState whenFalse) {
    _stateInternal = base;
    _stateAfterWhenTrueInternal = whenTrue;
    _stateAfterWhenFalseInternal = whenFalse;
  }

  final SideEffectsBuilder _sideEffectsBuilder;
  final Map<JumpTarget, List<LocalState>> _breaksFor =
      <JumpTarget, List<LocalState>>{};
  final Map<JumpTarget, List<LocalState>> _continuesFor =
      <JumpTarget, List<LocalState>>{};
  TypeInformation _returnType;
  final Set<Local> _capturedVariables = Set<Local>();
  final Map<Local, FieldEntity> _capturedAndBoxed;

  final StaticTypeProvider _staticTypeProvider;

  /// Whether we currently taken the boolean result of is-checks or null-checks
  /// into account in the local state.
  bool _accumulateIsChecks = false;

  KernelTypeGraphBuilder(
      this._options,
      this._closedWorld,
      this._inferrer,
      this._analyzedMember,
      this._analyzedNode,
      this._localsMap,
      this._staticTypeProvider,
      [this._stateInternal,
      Map<Local, FieldEntity> capturedAndBoxed])
      : this._types = _inferrer.types,
        this._memberData = _inferrer.dataOfMember(_analyzedMember),
        // TODO(johnniwinther): Should side effects also be tracked for field
        // initializers?
        this._sideEffectsBuilder = _analyzedMember is FunctionEntity
            ? _inferrer.inferredDataBuilder
                .getSideEffectsBuilder(_analyzedMember)
            : SideEffectsBuilder.free(_analyzedMember),
        this._inGenerativeConstructor = _analyzedNode is ir.Constructor,
        this._capturedAndBoxed = capturedAndBoxed != null
            ? Map<Local, FieldEntity>.from(capturedAndBoxed)
            : <Local, FieldEntity>{} {
    if (_state != null) return;

    _state =
        LocalState.initial(inGenerativeConstructor: _inGenerativeConstructor);
  }

  JsToElementMap get _elementMap => _closedWorld.elementMap;

  ClosureData get _closureDataLookup => _closedWorld.closureDataLookup;

  DartType _getStaticType(ir.Expression node) {
    return _elementMap.getDartType(_staticTypeProvider.getStaticType(node));
  }

  int _loopLevel = 0;

  bool get inLoop => _loopLevel > 0;

  /// Returns `true` if [member] is defined in a subclass of the current this
  /// type.
  bool _isInClassOrSubclass(MemberEntity member) {
    ClassEntity cls = _elementMap.getMemberThisType(_analyzedMember)?.element;
    if (cls == null) return false;
    return _closedWorld.classHierarchy.isSubclassOf(member.enclosingClass, cls);
  }

  /// Checks whether the access or update of [selector] on [mask] potentially
  /// exposes `this`.
  ///
  /// If all matching members are instance fields on the current `this`
  /// class or subclasses, `this` is not considered to be exposed.
  ///
  /// If an instance field matched with a [selector] that is _not_ a setter, the
  /// field is considered to have been read before initialization and the field
  /// is assumed to be potentially `null`.
  void _checkIfExposesThis(Selector selector, AbstractValue mask) {
    if (_state.isThisExposed) {
      // We already consider `this` to have been exposed.
      return;
    }
    if (_inferrer.closedWorld.includesClosureCall(selector, mask)) {
      // TODO(ngeoffray): We could do better here if we knew what we
      // are calling does not expose this.
      _state.markThisAsExposed();
    } else {
      _inferrer.forEachElementMatching(selector, mask, (MemberEntity element) {
        if (element != null && element.isField) {
          FieldEntity field = element;
          if (!selector.isSetter &&
              _isInClassOrSubclass(field) &&
              field.isAssignable &&
              _state.readField(field) == null &&
              getFieldInitializer(_elementMap, field) == 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.
        _state.markThisAsExposed();
        return false;
      });
    }
  }

  TypeInformation run() {
    if (_analyzedMember.isField) {
      if (_analyzedNode == null || isNullLiteral(_analyzedNode)) {
        // 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 = _closureDataLookup.getScopeInfo(_analyzedMember);
    scopeInfo.forEachBoxedVariable(_localsMap, (variable, field) {
      _capturedAndBoxed[variable] = field;
    });

    return visit(_analyzedNode);
  }

  bool isIncompatibleInvoke(FunctionEntity function, ArgumentsTypes arguments) {
    ParameterStructure parameterStructure = function.parameterStructure;

    return arguments.positional.length <
            parameterStructure.requiredPositionalParameters ||
        arguments.positional.length > parameterStructure.positionalParameters ||
        arguments.named.keys
            .any((name) => !parameterStructure.namedParameters.contains(name));
  }

  void recordReturnType(TypeInformation type) {
    FunctionEntity analyzedMethod = _analyzedMember;
    _returnType =
        _inferrer.addReturnTypeForMethod(analyzedMethod, _returnType, type);
  }

  TypeInformation _thisType;
  TypeInformation get thisType {
    if (_thisType != null) return _thisType;
    ClassEntity cls = _elementMap.getMemberThisType(_analyzedMember)?.element;
    if (_closedWorld.isUsedAsMixin(cls)) {
      return _thisType = _types.nonNullSubtype(cls);
    } else {
      return _thisType = _types.nonNullSubclass(cls);
    }
  }

  TypeInformation visit(ir.Node node, {bool conditionContext = false}) {
    var oldAccumulateIsChecks = _accumulateIsChecks;
    _accumulateIsChecks = conditionContext;
    var result = node?.accept(this);
    _accumulateIsChecks = oldAccumulateIsChecks;
    return result;
  }

  void visitList(List<ir.Node> nodes) {
    if (nodes == null) return;
    nodes.forEach(visit);
  }

  void handleParameter(ir.VariableDeclaration node, {bool isOptional}) {
    Local local = _localsMap.getLocalVariable(node);
    DartType type = _localsMap.getLocalType(_elementMap, local);
    _state.updateLocal(_inferrer, _capturedAndBoxed, local,
        _inferrer.typeOfParameter(local), node, type);
    if (isOptional) {
      TypeInformation type;
      if (node.initializer != null) {
        type = visit(node.initializer);
      } else {
        type = _types.nullType;
      }
      _inferrer.setDefaultTypeOfParameter(local, type,
          isInstanceMember: _analyzedMember.isInstanceMember);
    }
  }

  @override
  TypeInformation visitConstructor(ir.Constructor node) {
    handleParameters(node.function);
    node.initializers.forEach(visit);
    visit(node.function.body);

    ClassEntity cls = _analyzedMember.enclosingClass;
    if (!(node.initializers.isNotEmpty &&
        node.initializers.first is ir.RedirectingInitializer)) {
      // Iterate over all instance fields, and give a null type to
      // fields that we haven't initialized for sure.
      _elementMap.elementEnvironment.forEachLocalClassMember(cls,
          (MemberEntity member) {
        if (member.isField && member.isInstanceMember && member.isAssignable) {
          TypeInformation type = _state.readField(member);
          MemberDefinition definition = _elementMap.getMemberDefinition(member);
          assert(definition.kind == MemberKind.regular);
          ir.Field node = definition.node;
          if (type == null &&
              (node.initializer == null || isNullLiteral(node.initializer))) {
            _inferrer.recordTypeOfField(member, _types.nullType);
          }
        }
      });
    }
    _inferrer.recordExposesThis(_analyzedMember, _state.isThisExposed);

    if (cls.isAbstract) {
      if (_closedWorld.classHierarchy.isInstantiated(cls)) {
        _returnType = _types.nonNullSubclass(cls);
      } else {
        // TODO(johnniwinther): Avoid analyzing [_analyzedMember] in this
        // case; it's never called.
        _returnType = _types.nonNullEmpty();
      }
    } else {
      _returnType = _types.nonNullExact(cls);
    }
    assert(_breaksFor.isEmpty);
    assert(_continuesFor.isEmpty);
    return _returnType;
  }

  @override
  visitFieldInitializer(ir.FieldInitializer node) {
    TypeInformation rhsType = visit(node.value);
    FieldEntity field = _elementMap.getField(node.field);
    _state.updateField(field, rhsType);
    _inferrer.recordTypeOfField(field, rhsType);
    return null;
  }

  @override
  visitSuperInitializer(ir.SuperInitializer node) {
    ConstructorEntity constructor = _elementMap.getConstructor(node.target);
    ArgumentsTypes arguments = analyzeArguments(node.arguments);
    Selector selector = Selector(SelectorKind.CALL, constructor.memberName,
        _elementMap.getCallStructure(node.arguments));
    handleConstructorInvoke(
        node, node.arguments, selector, constructor, arguments);

    _inferrer.analyze(constructor);
    if (_inferrer.checkIfExposesThis(constructor)) {
      _state.markThisAsExposed();
    }
    return null;
  }

  @override
  visitRedirectingInitializer(ir.RedirectingInitializer node) {
    ConstructorEntity constructor = _elementMap.getConstructor(node.target);
    ArgumentsTypes arguments = analyzeArguments(node.arguments);
    Selector selector = Selector(SelectorKind.CALL, constructor.memberName,
        _elementMap.getCallStructure(node.arguments));
    handleConstructorInvoke(
        node, node.arguments, selector, constructor, arguments);

    _inferrer.analyze(constructor);
    if (_inferrer.checkIfExposesThis(constructor)) {
      _state.markThisAsExposed();
    }
    return null;
  }

  @override
  visitLocalInitializer(ir.LocalInitializer node) {
    visit(node.variable);
    return null;
  }

  void handleParameters(ir.FunctionNode node) {
    int position = 0;
    for (ir.VariableDeclaration parameter in node.positionalParameters) {
      handleParameter(parameter,
          isOptional: position >= node.requiredParameterCount);
      position++;
    }
    for (ir.VariableDeclaration parameter in node.namedParameters) {
      handleParameter(parameter, isOptional: true);
    }
  }

  @override
  TypeInformation visitFunctionNode(ir.FunctionNode node) {
    handleParameters(node);

    if (_closedWorld.nativeData.isNativeMember(_analyzedMember)) {
      // Native methods do not have a body, and we currently just say
      // they return dynamic and may contain all side-effects.
      NativeBehavior nativeBehavior =
          _closedWorld.nativeData.getNativeMethodBehavior(_analyzedMember);
      _sideEffectsBuilder.add(nativeBehavior.sideEffects);
      return _types.dynamicType;
    }

    visit(node.body);
    switch (node.asyncMarker) {
      case ir.AsyncMarker.Sync:
        if (_returnType == null) {
          // No return in the body.
          _returnType = _state.seenReturnOrThrow
              ? _types.nonNullEmpty() // Body always throws.
              : _types.nullType;
        } else if (!_state.seenReturnOrThrow) {
          // We haven'TypeInformation seen returns on all branches. So the
          // method may also return null.
          recordReturnType(_types.nullType);
        }
        break;

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

      case ir.AsyncMarker.Async:
        recordReturnType(_types.asyncFutureType);
        break;

      case ir.AsyncMarker.AsyncStar:
        recordReturnType(_types.asyncStarStreamType);
        break;
      case ir.AsyncMarker.SyncYielding:
        failedAt(
            _analyzedMember, "Unexpected async marker: ${node.asyncMarker}");
        break;
    }
    assert(_breaksFor.isEmpty);
    assert(_continuesFor.isEmpty);
    return _returnType;
  }

  @override
  TypeInformation visitInstantiation(ir.Instantiation node) {
    return createInstantiationTypeInformation(visit(node.expression));
  }

  TypeInformation createInstantiationTypeInformation(
      TypeInformation expressionType) {
    // TODO(sra): Add a TypeInformation for Instantiations.  Instantiated
    // generic methods will need to be traced separately, and have the
    // information gathered in tracing reflected back to the generic method. For
    // now, pass along the uninstantiated method.
    return expressionType;
  }

  @override
  TypeInformation defaultExpression(ir.Expression node) {
    throw UnimplementedError(
        'Unhandled expression: ${node} (${node.runtimeType})');
  }

  @override
  defaultStatement(ir.Statement node) {
    throw UnimplementedError(
        'Unhandled statement: ${node} (${node.runtimeType})');
  }

  @override
  TypeInformation visitNullLiteral(ir.NullLiteral literal) {
    return createNullTypeInformation();
  }

  TypeInformation createNullTypeInformation() {
    return _types.nullType;
  }

  @override
  visitBlock(ir.Block block) {
    for (ir.Statement statement in block.statements) {
      visit(statement);
      if (_state.aborts) break;
    }
    return null;
  }

  @override
  visitExpressionStatement(ir.ExpressionStatement node) {
    visit(node.expression);
    return null;
  }

  @override
  visitEmptyStatement(ir.EmptyStatement node) {
    // Nothing to do.
    return null;
  }

  TypeInformation _handleAssertStatement(ir.AssertStatement node) {
    // Avoid pollution from assert statement unless enabled.
    if (!_options.enableUserAssertions) {
      return null;
    }
    // TODO(johnniwinther): Should assert be used with --trust-type-annotations?
    // TODO(johnniwinther): Track reachable for assertions known to fail.
    LocalState stateBefore = _state;
    handleCondition(node.condition);
    LocalState afterConditionWhenTrue = _stateAfterWhenTrue;
    LocalState afterConditionWhenFalse = _stateAfterWhenFalse;
    _state = LocalState.childPath(afterConditionWhenFalse);
    visit(node.message);
    LocalState stateAfterMessage = _state;
    stateAfterMessage.seenReturnOrThrow = true;
    _state = stateBefore.mergeDiamondFlow(
        _inferrer, afterConditionWhenTrue, stateAfterMessage);
    return null;
  }

  @override
  visitAssertInitializer(ir.AssertInitializer node) {
    return _handleAssertStatement(node.statement);
  }

  @override
  visitAssertStatement(ir.AssertStatement node) {
    return _handleAssertStatement(node);
  }

  @override
  visitBreakStatement(ir.BreakStatement node) {
    JumpTarget target = _localsMap.getJumpTargetForBreak(node);
    _state.seenBreakOrContinue = true;
    // Do a deep-copy of the locals, because the code following the
    // break will change them.
    if (_localsMap.generateContinueForBreak(node)) {
      _continuesFor[target].add(LocalState.deepCopyOf(_state));
    } else {
      _breaksFor[target].add(LocalState.deepCopyOf(_state));
    }
    return null;
  }

  @override
  visitLabeledStatement(ir.LabeledStatement node) {
    ir.Statement body = node.body;
    if (JumpVisitor.canBeBreakTarget(body)) {
      // Loops and switches handle their own labels.
      visit(body);
    } else {
      LocalState stateBefore = _state;
      JumpTarget jumpTarget = _localsMap.getJumpTargetForLabel(node);
      _setupBreaksAndContinues(jumpTarget);
      _state = LocalState.childPath(stateBefore);
      visit(body);
      _state = stateBefore.mergeAfterBreaks(_inferrer, _getBreaks(jumpTarget),
          keepOwnLocals: false);
      _clearBreaksAndContinues(jumpTarget);
    }
    return null;
  }

  @override
  visitSwitchStatement(ir.SwitchStatement node) {
    visit(node.expression);

    JumpTarget jumpTarget = _localsMap.getJumpTargetForSwitch(node);
    _setupBreaksAndContinues(jumpTarget);

    List<JumpTarget> continueTargets = <JumpTarget>[];
    for (ir.SwitchCase switchCase in node.cases) {
      JumpTarget continueTarget =
          _localsMap.getJumpTargetForSwitchCase(switchCase);
      if (continueTarget != null) {
        continueTargets.add(continueTarget);
      }
    }
    if (continueTargets.isNotEmpty) {
      continueTargets.forEach(_setupBreaksAndContinues);

      // If the switch statement has a continue, we conservatively
      // visit all cases and update [locals] until we have reached a
      // fixed point.
      bool changed;
      _state.startLoop(_inferrer, node);
      do {
        changed = false;
        for (ir.SwitchCase switchCase in node.cases) {
          LocalState stateBeforeCase = _state;
          _state = LocalState.childPath(stateBeforeCase);
          visit(switchCase);
          LocalState stateAfterCase = _state;
          changed =
              stateBeforeCase.mergeAll(_inferrer, [stateAfterCase]) || changed;
          _state = stateBeforeCase;
        }
      } while (changed);
      _state.endLoop(_inferrer, node);

      continueTargets.forEach(_clearBreaksAndContinues);
    } else {
      LocalState stateBeforeCase = _state;
      List<LocalState> statesToMerge = <LocalState>[];
      bool hasDefaultCase = false;

      for (ir.SwitchCase switchCase in node.cases) {
        if (switchCase.isDefault) {
          hasDefaultCase = true;
        }
        _state = LocalState.childPath(stateBeforeCase);
        visit(switchCase);
        statesToMerge.add(_state);
      }
      stateBeforeCase.mergeAfterBreaks(_inferrer, statesToMerge,
          keepOwnLocals: !hasDefaultCase);
      _state = stateBeforeCase;
    }
    _clearBreaksAndContinues(jumpTarget);
    return null;
  }

  @override
  visitSwitchCase(ir.SwitchCase node) {
    visit(node.body);
    return null;
  }

  @override
  visitContinueSwitchStatement(ir.ContinueSwitchStatement node) {
    JumpTarget target = _localsMap.getJumpTargetForContinueSwitch(node);
    _state.seenBreakOrContinue = true;
    // Do a deep-copy of the locals, because the code following the
    // break will change them.
    _continuesFor[target].add(LocalState.deepCopyOf(_state));
    return null;
  }

  @override
  TypeInformation visitListLiteral(ir.ListLiteral node) {
    return createListTypeInformation(
        node, node.expressions.map((e) => visit(e)),
        isConst: node.isConst);
  }

  TypeInformation createListTypeInformation(
      ir.TreeNode node, Iterable<TypeInformation> elementTypes,
      {bool isConst}) {
    // 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 (TypeInformation type in elementTypes) {
        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 =
          isConst ? _types.constListType : _types.growableListType;
      return _types.allocateList(
          containerType, node, _analyzedMember, elementType, length);
    });
  }

  @override
  TypeInformation visitSetLiteral(ir.SetLiteral node) {
    return createSetTypeInformation(node, node.expressions.map((e) => visit(e)),
        isConst: node.isConst);
  }

  TypeInformation createSetTypeInformation(
      ir.TreeNode node, Iterable<TypeInformation> elementTypes,
      {bool isConst}) {
    return _inferrer.concreteTypes.putIfAbsent(node, () {
      TypeInformation elementType;
      for (TypeInformation type in elementTypes) {
        elementType = elementType == null
            ? _types.allocatePhi(null, null, type, isTry: false)
            : _types.addPhiInput(null, elementType, type);
      }
      elementType = elementType == null
          ? _types.nonNullEmpty()
          : _types.simplifyPhi(null, null, elementType);
      TypeInformation containerType =
          isConst ? _types.constSetType : _types.setType;
      return _types.allocateSet(
          containerType, node, _analyzedMember, elementType);
    });
  }

  @override
  TypeInformation visitMapLiteral(ir.MapLiteral node) {
    return createMapTypeInformation(
        node, node.entries.map((e) => Pair(visit(e.key), visit(e.value))),
        isConst: node.isConst);
  }

  TypeInformation createMapTypeInformation(ir.TreeNode node,
      Iterable<Pair<TypeInformation, TypeInformation>> entryTypes,
      {bool isConst}) {
    return _inferrer.concreteTypes.putIfAbsent(node, () {
      List keyTypes = <TypeInformation>[];
      List valueTypes = <TypeInformation>[];

      for (Pair<TypeInformation, TypeInformation> entryType in entryTypes) {
        keyTypes.add(entryType.a);
        valueTypes.add(entryType.b);
      }

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

  @override
  TypeInformation visitReturnStatement(ir.ReturnStatement node) {
    ir.Node expression = node.expression;
    recordReturnType(expression == null ? _types.nullType : visit(expression));
    _state.seenReturnOrThrow = true;
    _state.markInitializationAsIndefinite();
    return null;
  }

  @override
  TypeInformation visitBoolLiteral(ir.BoolLiteral node) {
    return createBoolTypeInformation(node.value);
  }

  TypeInformation createBoolTypeInformation(bool value) {
    return _types.boolLiteralType(value);
  }

  @override
  TypeInformation visitIntLiteral(ir.IntLiteral node) {
    return createIntTypeInformation(node.value);
  }

  TypeInformation createIntTypeInformation(int value) {
    // The JavaScript backend may turn this literal into a double at
    // runtime.
    return _types.getConcreteTypeFor(_closedWorld.abstractValueDomain
        .computeAbstractValueForConstant(
            constant_system.createIntFromInt(value)));
  }

  @override
  TypeInformation visitDoubleLiteral(ir.DoubleLiteral node) {
    return createDoubleTypeInformation(node.value);
  }

  TypeInformation createDoubleTypeInformation(double value) {
    // The JavaScript backend may turn this literal into a double at
    // runtime.
    return _types.getConcreteTypeFor(_closedWorld.abstractValueDomain
        .computeAbstractValueForConstant(constant_system.createDouble(value)));
  }

  @override
  TypeInformation visitStringLiteral(ir.StringLiteral node) {
    return createStringTypeInformation(node.value);
  }

  TypeInformation createStringTypeInformation(String value) {
    return _types.stringLiteralType(value);
  }

  @override
  TypeInformation visitStringConcatenation(ir.StringConcatenation 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;
  }

  @override
  TypeInformation visitSymbolLiteral(ir.SymbolLiteral node) {
    return createSymbolLiteralTypeInformation();
  }

  TypeInformation createSymbolLiteralTypeInformation() {
    return _types
        .nonNullSubtype(_closedWorld.commonElements.symbolImplementationClass);
  }

  @override
  TypeInformation visitTypeLiteral(ir.TypeLiteral node) {
    return createTypeLiteralInformation();
  }

  TypeInformation createTypeLiteralInformation() {
    return _types.typeType;
  }

  @override
  TypeInformation visitVariableDeclaration(ir.VariableDeclaration node) {
    assert(
        node.parent is! ir.FunctionNode, "Unexpected parameter declaration.");
    Local local = _localsMap.getLocalVariable(node);
    DartType type = _localsMap.getLocalType(_elementMap, local);
    if (node.initializer == null) {
      _state.updateLocal(
          _inferrer, _capturedAndBoxed, local, _types.nullType, node, type);
    } else {
      _state.updateLocal(_inferrer, _capturedAndBoxed, local,
          visit(node.initializer), node, type);
    }
    if (node.initializer is ir.ThisExpression) {
      _state.markThisAsExposed();
    }
    return null;
  }

  @override
  TypeInformation visitVariableGet(ir.VariableGet node) {
    Local local = _localsMap.getLocalVariable(node.variable);
    TypeInformation type =
        _state.readLocal(_inferrer, _capturedAndBoxed, local);
    assert(type != null, "Missing type information for $local.");
    return type;
  }

  @override
  TypeInformation visitVariableSet(ir.VariableSet node) {
    TypeInformation rhsType = visit(node.value);
    if (node.value is ir.ThisExpression) {
      _state.markThisAsExposed();
    }
    Local local = _localsMap.getLocalVariable(node.variable);
    DartType type = _localsMap.getLocalType(_elementMap, local);
    _state.updateLocal(
        _inferrer, _capturedAndBoxed, local, rhsType, node, type);
    return rhsType;
  }

  ArgumentsTypes analyzeArguments(ir.Arguments arguments) {
    List<TypeInformation> positional = <TypeInformation>[];
    Map<String, TypeInformation> named;
    for (ir.Expression argument in arguments.positional) {
      // TODO(ngeoffray): We could do better here if we knew what we
      // are calling does not expose this.
      if (argument is ir.ThisExpression) {
        _state.markThisAsExposed();
      }
      positional.add(visit(argument));
    }
    for (ir.NamedExpression argument in arguments.named) {
      named ??= <String, TypeInformation>{};
      ir.Expression value = argument.value;
      // TODO(ngeoffray): We could do better here if we knew what we
      // are calling does not expose this.
      if (value is ir.ThisExpression) {
        _state.markThisAsExposed();
      }
      named[argument.name] = visit(value);
    }

    return ArgumentsTypes(positional, named);
  }

  AbstractValue _typeOfReceiver(ir.TreeNode node, ir.TreeNode receiver) {
    KernelGlobalTypeInferenceElementData data = _memberData;
    AbstractValue mask = data.typeOfReceiver(node);
    if (mask != null) return mask;
    // TODO(sigmund): ensure that this is only called once per node.
    DartType staticType = _getStaticType(receiver);
    bool includeNull =
        _dartTypes.useLegacySubtyping || staticType is NullableType;
    staticType = staticType.withoutNullability;
    if (staticType is InterfaceType) {
      ClassEntity cls = staticType.element;
      if (receiver is ir.ThisExpression && !_closedWorld.isUsedAsMixin(cls)) {
        mask = _closedWorld.abstractValueDomain.createNonNullSubclass(cls);
      } else if (includeNull) {
        mask = _closedWorld.abstractValueDomain.createNullableSubtype(cls);
      } else {
        mask = _closedWorld.abstractValueDomain.createNonNullSubtype(cls);
      }
      data.setReceiverTypeMask(node, mask);
      return mask;
    }
    // TODO(sigmund): consider also extracting the bound of type parameters.
    return null;
  }

  TypeInformation _handleLocalFunctionInvocation(
      ir.Expression node,
      ir.FunctionDeclaration function,
      ir.Arguments arguments,
      Selector selector) {
    ArgumentsTypes argumentsTypes = analyzeArguments(arguments);
    ClosureRepresentationInfo info =
        _closureDataLookup.getClosureInfo(function);
    if (isIncompatibleInvoke(info.callMethod, argumentsTypes)) {
      return _types.dynamicType;
    }

    TypeInformation type =
        handleStaticInvoke(node, selector, info.callMethod, argumentsTypes);
    FunctionType functionType =
        _elementMap.elementEnvironment.getFunctionType(info.callMethod);
    if (functionType.returnType.containsFreeTypeVariables) {
      // The return type varies with the call site so we narrow the static
      // return type.
      type = _types.narrowType(type, _getStaticType(node));
    }
    return type;
  }

  @override
  TypeInformation visitLocalFunctionInvocation(
      ir.LocalFunctionInvocation node) {
    Selector selector = _elementMap.getSelector(node);
    return _handleLocalFunctionInvocation(
        node, node.variable.parent, node.arguments, selector);
  }

  @override
  TypeInformation visitEqualsNull(ir.EqualsNull node) {
    visit(node.expression);
    // TODO(johnniwinther). This triggers the computation of the mask for the
    // receiver of the call to `==`, which doesn't happen in this case. Remove
    // this when the ssa builder recognizes `== null` directly.
    _typeOfReceiver(node, node.expression);
    _potentiallyAddNullCheck(node, node.expression);
    return _types.boolType;
  }

  TypeInformation _handleMethodInvocation(
      ir.Expression node,
      ir.Expression receiver,
      TypeInformation receiverType,
      Selector selector,
      ArgumentsTypes arguments,
      ir.Member interfaceTarget) {
    AbstractValue mask = _typeOfReceiver(node, receiver);
    if (receiver is ir.ThisExpression) {
      _checkIfExposesThis(
          selector, _types.newTypedSelector(receiverType, mask));
    }
    TypeInformation type = handleDynamicInvoke(CallType.access, node, selector,
        mask, receiverType, arguments, _getVariableDeclaration(receiver));
    if (interfaceTarget != null) {
      if (interfaceTarget is ir.Procedure &&
          (interfaceTarget.kind == ir.ProcedureKind.Method ||
              interfaceTarget.kind == ir.ProcedureKind.Operator)) {
        // Pull the type from kernel (instead of from the J-model) because the
        // interface target might be abstract and therefore not part of the
        // J-model.
        ir.DartType returnType = interfaceTarget.function.returnType;
        // The return type varies with the call site so we narrow the static
        // return type.
        if (containsFreeVariables(returnType)) {
          type = _types.narrowType(type, _getStaticType(node));
        }
      } else {
        // The return type is thrown away when using [TypeMask]s; narrow to the
        // static return type.
        type = _types.narrowType(type, _getStaticType(node));
      }
    } else {
      // We don't have a known target but the static type hold some information
      // if it is a function type.
      type = _types.narrowType(type, _getStaticType(node));
    }
    return type;
  }

  TypeInformation _handleEqualsCall(
      ir.Expression node,
      ir.Expression left,
      TypeInformation leftType,
      ir.Expression right,
      TypeInformation rightType) {
    // TODO(johnniwinther). This triggers the computation of the mask for the
    // receiver of the call to `==`, which might not happen in this case. Remove
    // this when the ssa builder recognizes `== null` directly.
    _typeOfReceiver(node, left);
    bool leftIsNull = _types.isNull(leftType);
    bool rightIsNull = _types.isNull(rightType);
    if (leftIsNull) {
      // [right] is `null` if [node] evaluates to `true`.
      _potentiallyAddNullCheck(node, right);
    }
    if (rightIsNull) {
      // [left] is `null` if [node] evaluates to `true`.
      _potentiallyAddNullCheck(node, left);
    }
    if (leftIsNull || rightIsNull) {
      // `left == right` where `left` and/or `right` is known to have type
      // `Null` so we have no invocation to register.
      return _types.boolType;
    }
    Selector selector = Selector.binaryOperator('==');
    ArgumentsTypes arguments = ArgumentsTypes([rightType], null);
    return _handleMethodInvocation(
        node, left, leftType, selector, arguments, null);
  }

  @override
  TypeInformation visitEqualsCall(ir.EqualsCall node) {
    TypeInformation leftType = visit(node.left);
    TypeInformation rightType = visit(node.right);
    return _handleEqualsCall(node, node.left, leftType, node.right, rightType);
  }

  @override
  TypeInformation visitInstanceInvocation(ir.InstanceInvocation node) {
    Selector selector = _elementMap.getSelector(node);
    ir.Expression receiver = node.receiver;
    TypeInformation receiverType = visit(receiver);
    ArgumentsTypes arguments = analyzeArguments(node.arguments);
    return _handleMethodInvocation(node, node.receiver, receiverType, selector,
        arguments, node.interfaceTarget);
  }

  @override
  TypeInformation visitInstanceGetterInvocation(
      ir.InstanceGetterInvocation node) {
    Selector selector = _elementMap.getSelector(node);
    ir.Expression receiver = node.receiver;
    TypeInformation receiverType = visit(receiver);
    ArgumentsTypes arguments = analyzeArguments(node.arguments);
    return _handleMethodInvocation(node, node.receiver, receiverType, selector,
        arguments, node.interfaceTarget);
  }

  @override
  TypeInformation visitDynamicInvocation(ir.DynamicInvocation node) {
    Selector selector = _elementMap.getSelector(node);
    ir.Expression receiver = node.receiver;
    TypeInformation receiverType = visit(receiver);
    ArgumentsTypes arguments = analyzeArguments(node.arguments);
    return _handleMethodInvocation(
        node, node.receiver, receiverType, selector, arguments, null);
  }

  @override
  TypeInformation visitFunctionInvocation(ir.FunctionInvocation node) {
    Selector selector = _elementMap.getSelector(node);
    ir.Expression receiver = node.receiver;
    TypeInformation receiverType = visit(receiver);
    ArgumentsTypes arguments = analyzeArguments(node.arguments);
    return _handleMethodInvocation(
        node, node.receiver, receiverType, selector, arguments, null);
  }

  ir.VariableDeclaration _getVariableDeclaration(ir.Expression node) {
    return node is ir.VariableGet ? node.variable : null;
  }

  TypeInformation _handleDynamic(
      CallType callType,
      ir.Node node,
      Selector selector,
      AbstractValue mask,
      TypeInformation receiverType,
      ArgumentsTypes arguments,
      ir.VariableDeclaration variable) {
    assert(receiverType != null);
    if (_types.selectorNeedsUpdate(receiverType, mask)) {
      mask = receiverType == _types.dynamicType
          ? null
          : _types.newTypedSelector(receiverType, mask);
      _inferrer.updateSelectorInMember(
          _analyzedMember, callType, node, selector, mask);
    }

    if (variable != null) {
      Local local = _localsMap.getLocalVariable(variable);
      if (!_capturedVariables.contains(local)) {
        // Receiver strengthening to non-null.
        DartType type = _localsMap.getLocalType(_elementMap, local);
        _state.updateLocal(
            _inferrer, _capturedAndBoxed, local, receiverType, node, type,
            excludeNull: !selector.appliesToNullWithoutThrow());
      }
    }

    return _inferrer.registerCalledSelector(callType, node, selector, mask,
        receiverType, _analyzedMember, arguments, _sideEffectsBuilder,
        inLoop: inLoop, isConditional: false);
  }

  TypeInformation handleDynamicGet(
      ir.Node node,
      Selector selector,
      AbstractValue mask,
      TypeInformation receiverType,
      ir.VariableDeclaration variable) {
    return _handleDynamic(
        CallType.access, node, selector, mask, receiverType, null, variable);
  }

  TypeInformation handleDynamicSet(
      ir.Node node,
      Selector selector,
      AbstractValue mask,
      TypeInformation receiverType,
      TypeInformation rhsType,
      ir.VariableDeclaration variable) {
    ArgumentsTypes arguments = ArgumentsTypes([rhsType], null);
    return _handleDynamic(CallType.access, node, selector, mask, receiverType,
        arguments, variable);
  }

  TypeInformation handleDynamicInvoke(
      CallType callType,
      ir.Node node,
      Selector selector,
      AbstractValue mask,
      TypeInformation receiverType,
      ArgumentsTypes arguments,
      ir.VariableDeclaration variable) {
    return _handleDynamic(
        callType, node, selector, mask, receiverType, arguments, variable);
  }

  @override
  TypeInformation visitLet(ir.Let node) {
    visit(node.variable);
    return visit(node.body);
  }

  @override
  TypeInformation visitBlockExpression(ir.BlockExpression node) {
    visit(node.body);
    return visit(node.value);
  }

  @override
  TypeInformation visitForInStatement(ir.ForInStatement node) {
    if (node.iterable is ir.ThisExpression) {
      // Any reasonable implementation of an iterator would expose
      // this, so we play it safe and assume it will.
      _state.markThisAsExposed();
    }

    AbstractValue currentMask;
    AbstractValue moveNextMask;
    TypeInformation iteratorType;
    if (node.isAsync) {
      TypeInformation expressionType = visit(node.iterable);

      currentMask = _memberData.typeOfIteratorCurrent(node);
      moveNextMask = _memberData.typeOfIteratorMoveNext(node);

      ConstructorEntity constructor =
          _closedWorld.commonElements.streamIteratorConstructor;

      /// Synthesize a call to the [StreamIterator] constructor.
      iteratorType = handleStaticInvoke(
          node, null, constructor, ArgumentsTypes([expressionType], null));
    } else {
      TypeInformation expressionType = visit(node.iterable);
      Selector iteratorSelector = Selectors.iterator;
      AbstractValue iteratorMask = _memberData.typeOfIterator(node);
      currentMask = _memberData.typeOfIteratorCurrent(node);
      moveNextMask = _memberData.typeOfIteratorMoveNext(node);

      iteratorType = handleDynamicInvoke(CallType.forIn, node, iteratorSelector,
          iteratorMask, expressionType, ArgumentsTypes.empty(), null);
    }

    handleDynamicInvoke(CallType.forIn, node, Selectors.moveNext, moveNextMask,
        iteratorType, ArgumentsTypes.empty(), null);
    TypeInformation currentType = handleDynamicInvoke(
        CallType.forIn,
        node,
        Selectors.current,
        currentMask,
        iteratorType,
        ArgumentsTypes.empty(),
        null);

    Local variable = _localsMap.getLocalVariable(node.variable);
    DartType variableType = _localsMap.getLocalType(_elementMap, variable);
    _state.updateLocal(_inferrer, _capturedAndBoxed, variable, currentType,
        node.variable, variableType);

    JumpTarget target = _localsMap.getJumpTargetForForIn(node);
    return handleLoop(node, target, () {
      visit(node.body);
    });
  }

  void _setupBreaksAndContinues(JumpTarget target) {
    if (target == null) return;
    if (target.isContinueTarget) {
      _continuesFor[target] = <LocalState>[];
    }
    if (target.isBreakTarget) {
      _breaksFor[target] = <LocalState>[];
    }
  }

  void _clearBreaksAndContinues(JumpTarget element) {
    _continuesFor.remove(element);
    _breaksFor.remove(element);
  }

  List<LocalState> _getBreaks(JumpTarget target) {
    List<LocalState> list = <LocalState>[_state];
    if (target == null) return list;
    if (!target.isBreakTarget) return list;
    return list..addAll(_breaksFor[target]);
  }

  List<LocalState> _getLoopBackEdges(JumpTarget target) {
    List<LocalState> list = <LocalState>[_state];
    if (target == null) return list;
    if (!target.isContinueTarget) return list;
    return list..addAll(_continuesFor[target]);
  }

  TypeInformation handleLoop(ir.Node node, JumpTarget target, void logic()) {
    _loopLevel++;
    bool changed = false;
    LocalState stateBefore = _state;
    stateBefore.startLoop(_inferrer, 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);
      _state = LocalState.childPath(stateBefore);
      logic();
      changed = stateBefore.mergeAll(_inferrer, _getLoopBackEdges(target));
    } while (changed);
    _loopLevel--;
    stateBefore.endLoop(_inferrer, node);
    bool keepOwnLocals = node is! ir.DoStatement;
    _state = stateBefore.mergeAfterBreaks(_inferrer, _getBreaks(target),
        keepOwnLocals: keepOwnLocals);
    _clearBreaksAndContinues(target);
    return null;
  }

  @override
  TypeInformation visitConstructorInvocation(ir.ConstructorInvocation node) {
    ConstructorEntity constructor = _elementMap.getConstructor(node.target);
    ArgumentsTypes arguments = analyzeArguments(node.arguments);
    Selector selector = _elementMap.getSelector(node);
    return handleConstructorInvoke(
        node, node.arguments, selector, constructor, arguments);
  }

  /// Try to find the length given to a fixed array constructor call.
  int _findLength(ir.Arguments arguments) {
    int finish(int length) {
      // Filter out lengths that should not be tracked.
      if (length < 0) return null;
      // Serialization limit.
      if (length >= (1 << 30)) return null;
      return length;
    }

    ir.Expression firstArgument = arguments.positional.first;
    if (firstArgument is ir.ConstantExpression &&
        firstArgument.constant is ir.DoubleConstant) {
      ir.DoubleConstant constant = firstArgument.constant;
      double doubleValue = constant.value;
      int truncatedValue = doubleValue.truncate();
      if (doubleValue == truncatedValue) {
        return finish(truncatedValue);
      }
    } else if (firstArgument is ir.IntLiteral) {
      return finish(firstArgument.value);
    } else if (firstArgument is ir.StaticGet) {
      MemberEntity member = _elementMap.getMember(firstArgument.target);
      if (member.isField) {
        FieldAnalysisData fieldData =
            _closedWorld.fieldAnalysis.getFieldData(member);
        if (fieldData.isEffectivelyConstant && fieldData.constantValue.isInt) {
          IntConstantValue intValue = fieldData.constantValue;
          if (intValue.intValue.isValidInt) {
            return finish(intValue.intValue.toInt());
          }
        }
      }
    }
    return null;
  }

  /// Find the base type for a system List constructor from the value passed to
  /// the 'growable' argument. [defaultGrowable] is the default value of the
  /// 'growable' parameter.
  TypeInformation _listBaseType(ir.Arguments arguments,
      {bool defaultGrowable}) {
    TypeInformation finish(bool /*?*/ growable) {
      if (growable == true) return _types.growableListType;
      if (growable == false) return _types.fixedListType;
      return _types.mutableArrayType;
    }

    for (ir.NamedExpression named in arguments.named) {
      if (named.name == 'growable') {
        ir.Expression argument = named.value;
        if (argument is ir.BoolLiteral) return finish(argument.value);
        if (argument is ir.ConstantExpression) {
          ir.Constant constant = argument.constant;
          if (constant is ir.BoolConstant) return finish(constant.value);
        }
        // 'growable' is present, but indeterminate.
        return finish(null);
      }
    }
    // 'growable' is missing.
    return finish(defaultGrowable);
  }

  /// Returns `true` for constructors of typed arrays.
  bool _isConstructorOfTypedArraySubclass(ConstructorEntity constructor) {
    ClassEntity cls = constructor.enclosingClass;
    return cls.library.canonicalUri == Uris.dart__native_typed_data &&
        _closedWorld.nativeData.isNativeClass(cls) &&
        _closedWorld.classHierarchy
            .isSubtypeOf(cls, _closedWorld.commonElements.typedDataClass) &&
        _closedWorld.classHierarchy
            .isSubtypeOf(cls, _closedWorld.commonElements.listClass) &&
        constructor.name == '';
  }

  TypeInformation handleConstructorInvoke(
      ir.Node node,
      ir.Arguments arguments,
      Selector selector,
      ConstructorEntity constructor,
      ArgumentsTypes argumentsTypes) {
    TypeInformation returnType =
        handleStaticInvoke(node, selector, constructor, argumentsTypes);

    // See if we can replace the returned type with one that better describes
    // the operation. For system List constructors we can treat this as the
    // allocation point of a new collection. The static invoke above ensures
    // that the implementation of the constructor sees the arguments.

    var commonElements = _elementMap.commonElements;

    if (commonElements.isUnnamedListConstructor(constructor)) {
      // We have `new List(...)`.
      if (arguments.positional.isEmpty && arguments.named.isEmpty) {
        // We have `new List()`.
        return _inferrer.concreteTypes.putIfAbsent(
            node,
            () => _types.allocateList(_types.growableListType, node,
                _analyzedMember, _types.nonNullEmpty(), 0));
      } else {
        // We have `new List(len)`.
        int length = _findLength(arguments);
        return _inferrer.concreteTypes.putIfAbsent(
            node,
            () => _types.allocateList(_types.fixedListType, node,
                _analyzedMember, _types.nullType, length));
      }
    }

    if (commonElements.isNamedListConstructor('filled', constructor)) {
      // We have something like `List.filled(len, fill)`.
      int length = _findLength(arguments);
      TypeInformation elementType = argumentsTypes.positional[1];
      TypeInformation baseType =
          _listBaseType(arguments, defaultGrowable: false);
      return _inferrer.concreteTypes.putIfAbsent(
          node,
          () => _types.allocateList(
              baseType, node, _analyzedMember, elementType, length));
    }

    if (commonElements.isNamedListConstructor('generate', constructor)) {
      // We have something like `List.generate(len, generator)`.
      int length = _findLength(arguments);
      TypeInformation baseType =
          _listBaseType(arguments, defaultGrowable: true);
      TypeInformation closureArgumentInfo = argumentsTypes.positional[1];
      // If the argument is an immediate closure, the element type is that
      // returned by the closure.
      TypeInformation elementType;
      if (closureArgumentInfo is ClosureTypeInformation) {
        FunctionEntity closure = closureArgumentInfo.closure;
        elementType = _types.getInferredTypeOfMember(closure);
      }
      elementType ??= _types.dynamicType;
      return _inferrer.concreteTypes.putIfAbsent(
          node,
          () => _types.allocateList(
              baseType, node, _analyzedMember, elementType, length));
    }

    if (commonElements.isNamedListConstructor('empty', constructor)) {
      // We have something like `List.empty(growable: true)`.
      TypeInformation baseType =
          _listBaseType(arguments, defaultGrowable: false);
      TypeInformation elementType = _types.nonNullEmpty(); // No elements!
      return _inferrer.concreteTypes.putIfAbsent(
          node,
          () => _types.allocateList(
              baseType, node, _analyzedMember, elementType, 0));
    }
    if (commonElements.isNamedListConstructor('of', constructor) ||
        commonElements.isNamedListConstructor('from', constructor)) {
      // We have something like `List.of(elements)`.
      TypeInformation baseType =
          _listBaseType(arguments, defaultGrowable: true);
      // TODO(sra): Use static type to bound the element type, preferably as a
      // narrowing of all inputs.
      TypeInformation elementType = _types.dynamicType;
      return _inferrer.concreteTypes.putIfAbsent(
          node,
          () => _types.allocateList(
              baseType, node, _analyzedMember, elementType));
    }

    // `JSArray.fixed` corresponds to `new Array(length)`, which is a list
    // filled with `null`.
    if (commonElements.isNamedJSArrayConstructor('fixed', constructor)) {
      int length = _findLength(arguments);
      TypeInformation elementType = _types.nullType;
      return _inferrer.concreteTypes.putIfAbsent(
          node,
          () => _types.allocateList(_types.fixedListType, node, _analyzedMember,
              elementType, length));
    }

    // `JSArray.allocateFixed` creates an array with 'no elements'. The contract
    // is that the caller will assign a value to each member before any element
    // is accessed. We can start tracking the element type as 'bottom'.
    if (commonElements.isNamedJSArrayConstructor(
        'allocateFixed', constructor)) {
      int length = _findLength(arguments);
      TypeInformation elementType = _types.nonNullEmpty();
      return _inferrer.concreteTypes.putIfAbsent(
          node,
          () => _types.allocateList(_types.fixedListType, node, _analyzedMember,
              elementType, length));
    }

    // `JSArray.allocateGrowable` creates an array with 'no elements'. The
    // contract is that the caller will assign a value to each member before any
    // element is accessed. We can start tracking the element type as 'bottom'.
    if (commonElements.isNamedJSArrayConstructor(
        'allocateGrowable', constructor)) {
      int length = _findLength(arguments);
      TypeInformation elementType = _types.nonNullEmpty();
      return _inferrer.concreteTypes.putIfAbsent(
          node,
          () => _types.allocateList(_types.growableListType, node,
              _analyzedMember, elementType, length));
    }

    if (_isConstructorOfTypedArraySubclass(constructor)) {
      // We have something like `Uint32List(len)`.
      int length = _findLength(arguments);
      MemberEntity member = _elementMap.elementEnvironment
          .lookupClassMember(constructor.enclosingClass, '[]');
      TypeInformation elementType = _inferrer.returnTypeOfMember(member);
      return _inferrer.concreteTypes.putIfAbsent(
          node,
          () => _types.allocateList(
              _types.nonNullExact(constructor.enclosingClass),
              node,
              _analyzedMember,
              elementType,
              length));
    }

    return returnType;
  }

  TypeInformation handleStaticInvoke(ir.Node node, Selector selector,
      MemberEntity element, ArgumentsTypes arguments) {
    return _inferrer.registerCalledMember(node, selector, _analyzedMember,
        element, arguments, _sideEffectsBuilder, inLoop);
  }

  TypeInformation handleClosureCall(ir.Node node, Selector selector,
      MemberEntity member, ArgumentsTypes arguments) {
    return _inferrer.registerCalledClosure(
        node,
        selector,
        _inferrer.typeOfMember(member),
        _analyzedMember,
        arguments,
        _sideEffectsBuilder,
        inLoop: inLoop);
  }

  TypeInformation handleForeignInvoke(ir.StaticInvocation node,
      FunctionEntity function, ArgumentsTypes arguments, Selector selector) {
    String name = function.name;
    handleStaticInvoke(node, selector, function, arguments);
    if (name == Identifiers.JS) {
      NativeBehavior nativeBehavior =
          _elementMap.getNativeBehaviorForJsCall(node);
      _sideEffectsBuilder.add(nativeBehavior.sideEffects);
      return _inferrer.typeOfNativeBehavior(nativeBehavior);
    } else if (name == Identifiers.JS_EMBEDDED_GLOBAL) {
      NativeBehavior nativeBehavior =
          _elementMap.getNativeBehaviorForJsEmbeddedGlobalCall(node);
      _sideEffectsBuilder.add(nativeBehavior.sideEffects);
      return _inferrer.typeOfNativeBehavior(nativeBehavior);
    } else if (name == Identifiers.JS_BUILTIN) {
      NativeBehavior nativeBehavior =
          _elementMap.getNativeBehaviorForJsBuiltinCall(node);
      _sideEffectsBuilder.add(nativeBehavior.sideEffects);
      return _inferrer.typeOfNativeBehavior(nativeBehavior);
    } else if (name == Identifiers.JS_STRING_CONCAT) {
      return _types.stringType;
    } else if (_closedWorld.commonElements.isCreateJsSentinel(function)) {
      return _types.lateSentinelType;
    } else if (_closedWorld.commonElements.isIsJsSentinel(function)) {
      return _types.boolType;
    } else {
      _sideEffectsBuilder.setAllSideEffects();
      return _types.dynamicType;
    }
  }

  @override
  TypeInformation visitStaticInvocation(ir.StaticInvocation node) {
    MemberEntity member = _elementMap.getMember(node.target);
    ArgumentsTypes arguments = analyzeArguments(node.arguments);
    Selector selector = _elementMap.getSelector(node);
    if (_closedWorld.commonElements.isForeign(member)) {
      return handleForeignInvoke(node, member, arguments, selector);
    } else if (_closedWorld.commonElements.isLateReadCheck(member)) {
      // `_lateReadCheck` is essentially a narrowing to exclude the sentinel
      // value. In order to avoid poor inference resulting from a large
      // fan-in/fan-out, we perform the narrowing directly instead of creating a
      // [TypeInformation] for this member.
      handleStaticInvoke(node, selector, member, arguments);
      return _types.narrowType(arguments.positional[0],
          _elementMap.getDartType(node.arguments.types.single),
          excludeLateSentinel: true);
    } else if (_closedWorld.commonElements.isCreateSentinel(member)) {
      handleStaticInvoke(node, selector, member, arguments);
      return _types.lateSentinelType;
    } else if (member.isConstructor) {
      return handleConstructorInvoke(
          node, node.arguments, selector, member, arguments);
    } else {
      assert(member.isFunction, "Unexpected static invocation target: $member");
      TypeInformation type =
          handleStaticInvoke(node, selector, member, arguments);
      FunctionType functionType =
          _elementMap.elementEnvironment.getFunctionType(member);
      if (functionType.returnType.containsFreeTypeVariables) {
        // The return type varies with the call site so we narrow the static
        // return type.
        type = _types.narrowType(type, _getStaticType(node));
      }
      return type;
    }
  }

  @override
  TypeInformation visitLoadLibrary(ir.LoadLibrary node) {
    // TODO(johnniwinther): Improve this by returning a Future type instead.
    return _types.dynamicType;
  }

  @override
  TypeInformation visitStaticGet(ir.StaticGet node) {
    return createStaticGetTypeInformation(node, node.target);
  }

  @override
  TypeInformation visitStaticTearOff(ir.StaticTearOff node) {
    return createStaticGetTypeInformation(node, node.target);
  }

  TypeInformation createStaticGetTypeInformation(
      ir.Node node, ir.Member target) {
    MemberEntity member = _elementMap.getMember(target);
    return handleStaticInvoke(
        node, Selector.getter(member.memberName), member, null);
  }

  @override
  TypeInformation visitStaticSet(ir.StaticSet node) {
    TypeInformation rhsType = visit(node.value);
    if (node.value is ir.ThisExpression) {
      _state.markThisAsExposed();
    }
    MemberEntity member = _elementMap.getMember(node.target);
    handleStaticInvoke(node, Selector.setter(member.memberName), member,
        ArgumentsTypes([rhsType], null));
    return rhsType;
  }

  TypeInformation _handlePropertyGet(ir.Expression node, ir.Expression receiver,
      {ir.Member interfaceTarget}) {
    TypeInformation receiverType = visit(receiver);
    Selector selector = _elementMap.getSelector(node);
    AbstractValue mask = _typeOfReceiver(node, receiver);
    if (receiver is ir.ThisExpression) {
      _checkIfExposesThis(
          selector, _types.newTypedSelector(receiverType, mask));
    }
    TypeInformation type = handleDynamicGet(
        node, selector, mask, receiverType, _getVariableDeclaration(receiver));
    if (interfaceTarget != null) {
      // Pull the type from kernel (instead of from the J-model) because the
      // interface target might be abstract and therefore not part of the
      // J-model.
      ir.DartType resultType = interfaceTarget.getterType;
      // The result type varies with the call site so we narrow the static
      // result type.
      if (containsFreeVariables(resultType)) {
        type = _types.narrowType(type, _getStaticType(node));
      }
    }
    return type;
  }

  @override
  TypeInformation visitInstanceGet(ir.InstanceGet node) {
    return _handlePropertyGet(node, node.receiver,
        interfaceTarget: node.interfaceTarget);
  }

  @override
  TypeInformation visitInstanceTearOff(ir.InstanceTearOff node) {
    return _handlePropertyGet(node, node.receiver,
        interfaceTarget: node.interfaceTarget);
  }

  @override
  TypeInformation visitDynamicGet(ir.DynamicGet node) {
    return _handlePropertyGet(node, node.receiver);
  }

  @override
  TypeInformation visitFunctionTearOff(ir.FunctionTearOff node) {
    return _handlePropertyGet(node, node.receiver);
  }

  TypeInformation _handlePropertySet(
      ir.Expression node, ir.Expression receiver, ir.Expression value,
      {ir.Member interfaceTarget}) {
    TypeInformation receiverType = visit(receiver);
    Selector selector = _elementMap.getSelector(node);
    AbstractValue mask = _typeOfReceiver(node, receiver);

    TypeInformation rhsType = visit(value);
    if (value is ir.ThisExpression) {
      _state.markThisAsExposed();
    }

    if (_inGenerativeConstructor && receiver is ir.ThisExpression) {
      AbstractValue typedMask = _types.newTypedSelector(receiverType, mask);
      if (!_closedWorld.includesClosureCall(selector, typedMask)) {
        Iterable<MemberEntity> targets =
            _closedWorld.locateMembers(selector, typedMask);
        // 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) {
          MemberEntity single = targets.first;
          if (single.isField) {
            FieldEntity field = single;
            _state.updateField(field, rhsType);
          }
        }
      }
    }
    if (receiver is ir.ThisExpression) {
      _checkIfExposesThis(
          selector, _types.newTypedSelector(receiverType, mask));
    }
    handleDynamicSet(node, selector, mask, receiverType, rhsType,
        _getVariableDeclaration(receiver));
    return rhsType;
  }

  @override
  TypeInformation visitInstanceSet(ir.InstanceSet node) {
    return _handlePropertySet(node, node.receiver, node.value,
        interfaceTarget: node.interfaceTarget);
  }

  @override
  TypeInformation visitDynamicSet(ir.DynamicSet node) {
    return _handlePropertySet(node, node.receiver, node.value);
  }

  @override
  TypeInformation visitThisExpression(ir.ThisExpression node) {
    return thisType;
  }

  TypeInformation handleCondition(ir.Node node) {
    bool oldAccumulateIsChecks = _accumulateIsChecks;
    _accumulateIsChecks = true;
    TypeInformation result = visit(node, conditionContext: true);
    _accumulateIsChecks = oldAccumulateIsChecks;
    return result;
  }

  void _potentiallyAddIsCheck(ir.IsExpression node) {
    if (!_accumulateIsChecks) return;
    ir.Expression operand = node.operand;
    if (operand is ir.VariableGet) {
      Local local = _localsMap.getLocalVariable(operand.variable);
      DartType localType = _elementMap.getDartType(node.type);
      LocalState stateAfterCheckWhenTrue = LocalState.childPath(_state);
      LocalState stateAfterCheckWhenFalse = LocalState.childPath(_state);

      // Narrow variable to tested type on true branch.
      TypeInformation currentTypeInformation = stateAfterCheckWhenTrue
          .readLocal(_inferrer, _capturedAndBoxed, local);
      stateAfterCheckWhenTrue.updateLocal(_inferrer, _capturedAndBoxed, local,
          currentTypeInformation, node, localType,
          isCast: false);
      _setStateAfter(_state, stateAfterCheckWhenTrue, stateAfterCheckWhenFalse);
    }
  }

  void _potentiallyAddNullCheck(ir.Expression node, ir.Expression receiver) {
    if (!_accumulateIsChecks) return;
    if (receiver is ir.VariableGet) {
      Local local = _localsMap.getLocalVariable(receiver.variable);
      DartType localType = _localsMap.getLocalType(_elementMap, local);
      LocalState stateAfterCheckWhenNull = LocalState.childPath(_state);
      LocalState stateAfterCheckWhenNotNull = LocalState.childPath(_state);

      // Narrow tested variable to 'Null' on true branch.
      stateAfterCheckWhenNull.updateLocal(_inferrer, _capturedAndBoxed, local,
          _types.nullType, node, localType);

      // Narrow tested variable to 'not null' on false branch.
      TypeInformation currentTypeInformation = stateAfterCheckWhenNotNull
          .readLocal(_inferrer, _capturedAndBoxed, local);
      stateAfterCheckWhenNotNull.updateLocal(
          _inferrer,
          _capturedAndBoxed,
          local,
          currentTypeInformation,
          node,
          _closedWorld.commonElements.objectType,
          excludeNull: true);
      _setStateAfter(
          _state, stateAfterCheckWhenNull, stateAfterCheckWhenNotNull);
    }
  }

  @override
  TypeInformation visitIfStatement(ir.IfStatement node) {
    LocalState stateBefore = _state;
    handleCondition(node.condition);
    LocalState stateAfterConditionWhenTrue = _stateAfterWhenTrue;
    LocalState stateAfterConditionWhenFalse = _stateAfterWhenFalse;
    _state = LocalState.childPath(stateAfterConditionWhenTrue);
    visit(node.then);
    LocalState stateAfterThen = _state;
    _state = LocalState.childPath(stateAfterConditionWhenFalse);
    visit(node.otherwise);
    LocalState stateAfterElse = _state;
    _state =
        stateBefore.mergeDiamondFlow(_inferrer, stateAfterThen, stateAfterElse);
    return null;
  }

  @override
  TypeInformation visitIsExpression(ir.IsExpression node) {
    visit(node.operand);
    _potentiallyAddIsCheck(node);
    return _types.boolType;
  }

  @override
  TypeInformation visitNot(ir.Not node) {
    visit(node.operand, conditionContext: _accumulateIsChecks);
    LocalState stateAfterOperandWhenTrue = _stateAfterWhenTrue;
    LocalState stateAfterOperandWhenFalse = _stateAfterWhenFalse;
    _setStateAfter(
        _state, stateAfterOperandWhenFalse, stateAfterOperandWhenTrue);
    // TODO(sra): Improve precision on constant and bool-conversion-to-constant
    // inputs.
    return _types.boolType;
  }

  @override
  TypeInformation visitLogicalExpression(ir.LogicalExpression node) {
    if (node.operatorEnum == ir.LogicalExpressionOperator.AND) {
      LocalState stateBefore = _state;
      _state = LocalState.childPath(stateBefore);
      TypeInformation leftInfo = handleCondition(node.left);
      LocalState stateAfterLeftWhenTrue = _stateAfterWhenTrue;
      LocalState stateAfterLeftWhenFalse = _stateAfterWhenFalse;
      _state = LocalState.childPath(stateAfterLeftWhenTrue);
      TypeInformation rightInfo = handleCondition(node.right);
      LocalState stateAfterRightWhenTrue = _stateAfterWhenTrue;
      LocalState stateAfterRightWhenFalse = _stateAfterWhenFalse;
      LocalState stateAfterWhenTrue = stateAfterRightWhenTrue;
      LocalState stateAfterWhenFalse = LocalState.childPath(stateBefore)
          .mergeDiamondFlow(
              _inferrer, stateAfterLeftWhenFalse, stateAfterRightWhenFalse);
      LocalState after = stateBefore.mergeDiamondFlow(
          _inferrer, stateAfterWhenTrue, stateAfterWhenFalse);
      _setStateAfter(after, stateAfterWhenTrue, stateAfterWhenFalse);
      // Constant-fold result.
      if (_types.isLiteralFalse(leftInfo)) return leftInfo;
      if (_types.isLiteralTrue(leftInfo)) {
        if (_types.isLiteralFalse(rightInfo)) return rightInfo;
        if (_types.isLiteralTrue(rightInfo)) return rightInfo;
      }
      // TODO(sra): Add a selector/mux node to improve precision.
      return _types.boolType;
    } else if (node.operatorEnum == ir.LogicalExpressionOperator.OR) {
      LocalState stateBefore = _state;
      _state = LocalState.childPath(stateBefore);
      TypeInformation leftInfo = handleCondition(node.left);
      LocalState stateAfterLeftWhenTrue = _stateAfterWhenTrue;
      LocalState stateAfterLeftWhenFalse = _stateAfterWhenFalse;
      _state = LocalState.childPath(stateAfterLeftWhenFalse);
      TypeInformation rightInfo = handleCondition(node.right);
      LocalState stateAfterRightWhenTrue = _stateAfterWhenTrue;
      LocalState stateAfterRightWhenFalse = _stateAfterWhenFalse;
      LocalState stateAfterWhenTrue = LocalState.childPath(stateBefore)
          .mergeDiamondFlow(
              _inferrer, stateAfterLeftWhenTrue, stateAfterRightWhenTrue);
      LocalState stateAfterWhenFalse = stateAfterRightWhenFalse;
      LocalState stateAfter = stateBefore.mergeDiamondFlow(
          _inferrer, stateAfterWhenTrue, stateAfterWhenFalse);
      _setStateAfter(stateAfter, stateAfterWhenTrue, stateAfterWhenFalse);
      // Constant-fold result.
      if (_types.isLiteralTrue(leftInfo)) return leftInfo;
      if (_types.isLiteralFalse(leftInfo)) {
        if (_types.isLiteralTrue(rightInfo)) return rightInfo;
        if (_types.isLiteralFalse(rightInfo)) return rightInfo;
      }
      // TODO(sra): Add a selector/mux node to improve precision.
      return _types.boolType;
    }
    failedAt(CURRENT_ELEMENT_SPANNABLE,
        "Unexpected logical operator '${node.operatorEnum}'.");
    return null;
  }

  @override
  TypeInformation visitConditionalExpression(ir.ConditionalExpression node) {
    LocalState stateBefore = _state;
    handleCondition(node.condition);
    LocalState stateAfterWhenTrue = _stateAfterWhenTrue;
    LocalState stateAfterWhenFalse = _stateAfterWhenFalse;
    _state = LocalState.childPath(stateAfterWhenTrue);
    TypeInformation firstType = visit(node.then);
    LocalState stateAfterThen = _state;
    _state = LocalState.childPath(stateAfterWhenFalse);
    TypeInformation secondType = visit(node.otherwise);
    LocalState stateAfterElse = _state;
    _state =
        stateBefore.mergeDiamondFlow(_inferrer, stateAfterThen, stateAfterElse);
    return _types.allocateDiamondPhi(firstType, secondType);
  }

  TypeInformation handleLocalFunction(
      ir.TreeNode node, ir.FunctionNode functionNode,
      [ir.VariableDeclaration variable]) {
    // 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. Possibly using
    // whether the created closure as a `thisLocal`.
    _state.markThisAsExposed();

    ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);

    // Record the types of captured non-boxed variables. Types of
    // these variables may already be there, because of an analysis of
    // a previous closure.
    info.forEachFreeVariable(_localsMap, (Local variable, FieldEntity field) {
      if (!info.isBoxedVariable(_localsMap, variable)) {
        if (variable == info.thisLocal) {
          _inferrer.recordTypeOfField(field, thisType);
        }
        TypeInformation localType =
            _state.readLocal(_inferrer, _capturedAndBoxed, variable);
        // The type is null for type parameters.
        if (localType != null) {
          _inferrer.recordTypeOfField(field, localType);
        }
      }
      _capturedVariables.add(variable);
    });

    TypeInformation localFunctionType =
        _inferrer.concreteTypes.putIfAbsent(node, () {
      return _types.allocateClosure(info.callMethod);
    });
    if (variable != null) {
      Local local = _localsMap.getLocalVariable(variable);
      DartType type = _localsMap.getLocalType(_elementMap, local);
      _state.updateLocal(
          _inferrer, _capturedAndBoxed, local, localFunctionType, node, type,
          excludeNull: true);
    }

    // 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.
    LocalState closureState = LocalState.closure(_state);
    KernelTypeGraphBuilder visitor = KernelTypeGraphBuilder(
        _options,
        _closedWorld,
        _inferrer,
        info.callMethod,
        functionNode,
        _localsMap,
        _staticTypeProvider,
        closureState,
        _capturedAndBoxed);
    visitor.run();
    _inferrer.recordReturnType(info.callMethod, visitor._returnType);

    return localFunctionType;
  }

  @override
  TypeInformation visitFunctionDeclaration(ir.FunctionDeclaration node) {
    return handleLocalFunction(node, node.function, node.variable);
  }

  @override
  TypeInformation visitFunctionExpression(ir.FunctionExpression node) {
    return handleLocalFunction(node, node.function);
  }

  @override
  visitWhileStatement(ir.WhileStatement node) {
    return handleLoop(node, _localsMap.getJumpTargetForWhile(node), () {
      handleCondition(node.condition);
      _state = LocalState.childPath(_stateAfterWhenTrue);
      visit(node.body);
    });
  }

  @override
  visitDoStatement(ir.DoStatement node) {
    return handleLoop(node, _localsMap.getJumpTargetForDo(node), () {
      visit(node.body);
      handleCondition(node.condition);
      // 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.
      //
      //     _state = new LocalState.childPath(_stateAfterWhenTrue, node.body);
    });
  }

  @override
  visitForStatement(ir.ForStatement node) {
    for (ir.VariableDeclaration variable in node.variables) {
      visit(variable);
    }
    return handleLoop(node, _localsMap.getJumpTargetForFor(node), () {
      handleCondition(node.condition);
      _state = LocalState.childPath(_stateAfterWhenTrue);
      visit(node.body);
      for (ir.Expression update in node.updates) {
        visit(update);
      }
    });
  }

  @override
  visitTryCatch(ir.TryCatch node) {
    LocalState stateBefore = _state;
    _state = LocalState.tryBlock(stateBefore, node);
    _state.markInitializationAsIndefinite();
    visit(node.body);
    LocalState stateAfterBody = _state;
    _state = stateBefore.mergeFlow(_inferrer, stateAfterBody);
    for (ir.Catch catchBlock in node.catches) {
      LocalState stateBeforeCatch = _state;
      _state = LocalState.childPath(stateBeforeCatch);
      visit(catchBlock);
      LocalState stateAfterCatch = _state;
      _state = stateBeforeCatch.mergeFlow(_inferrer, stateAfterCatch);
    }
    return null;
  }

  @override
  visitTryFinally(ir.TryFinally node) {
    LocalState stateBefore = _state;
    _state = LocalState.tryBlock(stateBefore, node);
    _state.markInitializationAsIndefinite();
    visit(node.body);
    LocalState stateAfterBody = _state;
    _state = stateBefore.mergeFlow(_inferrer, stateAfterBody);
    visit(node.finalizer);
    return null;
  }

  @override
  visitCatch(ir.Catch node) {
    ir.VariableDeclaration exception = node.exception;
    if (exception != null) {
      TypeInformation mask;
      DartType type = node.guard != null
          ? _elementMap.getDartType(node.guard).withoutNullability
          : _dartTypes.dynamicType();
      if (type is InterfaceType) {
        InterfaceType interfaceType = type;
        mask = _types.nonNullSubtype(interfaceType.element);
      } else {
        mask = _types.dynamicType;
      }
      Local local = _localsMap.getLocalVariable(exception);
      _state.updateLocal(_inferrer, _capturedAndBoxed, local, mask, node,
          _dartTypes.dynamicType(),
          excludeNull: true /* `throw null` produces a NullThrownError */);
    }
    ir.VariableDeclaration stackTrace = node.stackTrace;
    if (stackTrace != null) {
      Local local = _localsMap.getLocalVariable(stackTrace);
      // TODO(johnniwinther): Use a mask based on [StackTrace].
      // Note: stack trace may be null if users omit a stack in
      // `completer.completeError`.
      _state.updateLocal(_inferrer, _capturedAndBoxed, local,
          _types.dynamicType, node, _dartTypes.dynamicType());
    }
    visit(node.body);
    return null;
  }

  @override
  TypeInformation visitThrow(ir.Throw node) {
    visit(node.expression);
    _state.seenReturnOrThrow = true;
    return _types.nonNullEmpty();
  }

  @override
  TypeInformation visitRethrow(ir.Rethrow node) {
    _state.seenReturnOrThrow = true;
    return _types.nonNullEmpty();
  }

  TypeInformation handleSuperNoSuchMethod(
      ir.Node node, Selector selector, ArgumentsTypes arguments) {
    // Ensure we create a node, to make explicit the call to the
    // `noSuchMethod` handler.
    FunctionEntity noSuchMethod =
        _elementMap.getSuperNoSuchMethod(_analyzedMember.enclosingClass);
    return handleStaticInvoke(node, selector, noSuchMethod, arguments);
  }

  @override
  TypeInformation visitSuperPropertyGet(ir.SuperPropertyGet node) {
    // TODO(herhut): We could do better here if we knew what we
    // are calling does not expose this.
    _state.markThisAsExposed();

    ir.Member target = getEffectiveSuperTarget(node.interfaceTarget);
    Selector selector = Selector.getter(_elementMap.getName(node.name));
    if (target == null) {
      // TODO(johnniwinther): Remove this when the CFE checks for missing
      //  concrete super targets.
      return handleSuperNoSuchMethod(node, selector, null);
    }
    MemberEntity member = _elementMap.getMember(target);
    assert(member != null, "No member found for super property get: $node");
    TypeInformation type = handleStaticInvoke(node, selector, member, null);
    if (member.isGetter) {
      FunctionType functionType =
          _elementMap.elementEnvironment.getFunctionType(member);
      if (functionType.returnType.containsFreeTypeVariables) {
        // The result type varies with the call site so we narrow the static
        // result type.
        type = _types.narrowType(type, _getStaticType(node));
      }
    } else if (member.isField) {
      DartType fieldType = _elementMap.elementEnvironment.getFieldType(member);
      if (fieldType.containsFreeTypeVariables) {
        // The result type varies with the call site so we narrow the static
        // result type.
        type = _types.narrowType(type, _getStaticType(node));
      }
    }
    return type;
  }

  @override
  TypeInformation visitSuperPropertySet(ir.SuperPropertySet node) {
    // TODO(herhut): We could do better here if we knew what we
    // are calling does not expose this.
    _state.markThisAsExposed();

    TypeInformation rhsType = visit(node.value);
    ir.Member target = getEffectiveSuperTarget(node.interfaceTarget);
    Selector selector = Selector.setter(_elementMap.getName(node.name));
    ArgumentsTypes arguments = ArgumentsTypes([rhsType], null);
    if (target == null) {
      // TODO(johnniwinther): Remove this when the CFE checks for missing
      //  concrete super targets.
      return handleSuperNoSuchMethod(node, selector, arguments);
    }
    MemberEntity member = _elementMap.getMember(target);
    assert(member != null, "No member found for super property set: $node");
    handleStaticInvoke(node, selector, member, arguments);
    return rhsType;
  }

  @override
  TypeInformation visitSuperMethodInvocation(ir.SuperMethodInvocation node) {
    // TODO(herhut): We could do better here if we knew what we
    // are calling does not expose this.
    _state.markThisAsExposed();

    ir.Member target = getEffectiveSuperTarget(node.interfaceTarget);
    ArgumentsTypes arguments = analyzeArguments(node.arguments);
    Selector selector = _elementMap.getSelector(node);
    if (target == null) {
      // TODO(johnniwinther): Remove this when the CFE checks for missing
      //  concrete super targets.
      return handleSuperNoSuchMethod(node, selector, arguments);
    }
    MemberEntity member = _elementMap.getMember(target);
    assert(member.isFunction, "Unexpected super invocation target: $member");
    if (isIncompatibleInvoke(member, arguments)) {
      return handleSuperNoSuchMethod(node, selector, arguments);
    } else {
      TypeInformation type =
          handleStaticInvoke(node, selector, member, arguments);
      FunctionType functionType =
          _elementMap.elementEnvironment.getFunctionType(member);
      if (functionType.returnType.containsFreeTypeVariables) {
        // The return type varies with the call site so we narrow the static
        // return type.
        type = _types.narrowType(type, _getStaticType(node));
      }
      return type;
    }
  }

  @override
  TypeInformation visitAsExpression(ir.AsExpression node) {
    TypeInformation operandType = visit(node.operand);
    return _types.narrowType(operandType, _elementMap.getDartType(node.type));
  }

  @override
  TypeInformation visitNullCheck(ir.NullCheck node) {
    TypeInformation operandType = visit(node.operand);
    return _types.narrowType(operandType, _getStaticType(node));
  }

  @override
  TypeInformation visitAwaitExpression(ir.AwaitExpression node) {
    TypeInformation futureType = visit(node.operand);
    return _inferrer.registerAwait(node, futureType);
  }

  @override
  TypeInformation visitYieldStatement(ir.YieldStatement node) {
    TypeInformation operandType = visit(node.expression);
    return _inferrer.registerYield(node, operandType);
  }

  @override
  TypeInformation visitCheckLibraryIsLoaded(ir.CheckLibraryIsLoaded node) {
    return _types.nonNullEmpty();
  }

  @override
  TypeInformation visitInvalidExpression(ir.InvalidExpression node) {
    // TODO(johnniwinther): Maybe this should be [empty] instead?
    return _types.dynamicType;
  }

  @override
  TypeInformation visitConstantExpression(ir.ConstantExpression node) {
    return TypeInformationConstantVisitor(this, node)
        .visitConstant(node.constant);
  }
}

class TypeInformationConstantVisitor
    extends ir.ComputeOnceConstantVisitor<TypeInformation> {
  final KernelTypeGraphBuilder builder;
  final ir.ConstantExpression expression;

  TypeInformationConstantVisitor(this.builder, this.expression);

  @override
  TypeInformation defaultConstant(ir.Constant node) {
    throw UnsupportedError("Unexpected constant: "
        "${node} (${node.runtimeType})");
  }

  @override
  TypeInformation visitNullConstant(ir.NullConstant node) {
    return builder.createNullTypeInformation();
  }

  @override
  TypeInformation visitBoolConstant(ir.BoolConstant node) {
    return builder.createBoolTypeInformation(node.value);
  }

  @override
  TypeInformation visitIntConstant(ir.IntConstant node) {
    return builder.createIntTypeInformation(node.value);
  }

  @override
  TypeInformation visitDoubleConstant(ir.DoubleConstant node) {
    return builder.createDoubleTypeInformation(node.value);
  }

  @override
  TypeInformation visitStringConstant(ir.StringConstant node) {
    return builder.createStringTypeInformation(node.value);
  }

  @override
  TypeInformation visitSymbolConstant(ir.SymbolConstant node) {
    return builder.createSymbolLiteralTypeInformation();
  }

  @override
  TypeInformation visitMapConstant(ir.MapConstant node) {
    return builder.createMapTypeInformation(
        ConstantReference(expression, node),
        node.entries
            .map((e) => Pair(visitConstant(e.key), visitConstant(e.value))),
        isConst: true);
  }

  @override
  TypeInformation visitListConstant(ir.ListConstant node) {
    return builder.createListTypeInformation(
        ConstantReference(expression, node),
        node.entries.map((e) => visitConstant(e)),
        isConst: true);
  }

  @override
  TypeInformation visitSetConstant(ir.SetConstant node) {
    return builder.createSetTypeInformation(ConstantReference(expression, node),
        node.entries.map((e) => visitConstant(e)),
        isConst: true);
  }

  @override
  TypeInformation visitInstanceConstant(ir.InstanceConstant node) {
    node.fieldValues.forEach((ir.Reference reference, ir.Constant value) {
      builder._inferrer.recordTypeOfField(
          builder._elementMap.getField(reference.asField),
          visitConstant(value));
    });
    return builder._types.getConcreteTypeFor(builder
        ._closedWorld.abstractValueDomain
        .createNonNullExact(builder._elementMap.getClass(node.classNode)));
  }

  @override
  TypeInformation visitInstantiationConstant(ir.InstantiationConstant node) {
    return builder.createInstantiationTypeInformation(
        visitConstant(node.tearOffConstant));
  }

  @override
  TypeInformation visitStaticTearOffConstant(ir.StaticTearOffConstant node) {
    return builder.createStaticGetTypeInformation(node, node.target);
  }

  @override
  TypeInformation visitTypeLiteralConstant(ir.TypeLiteralConstant node) {
    return builder.createTypeLiteralInformation();
  }

  @override
  TypeInformation visitUnevaluatedConstant(ir.UnevaluatedConstant node) {
    assert(false, "Unexpected unevaluated constant: $node");
    return builder._types.dynamicType;
  }
}

class Refinement {
  final Selector selector;
  final AbstractValue mask;

  Refinement(this.selector, this.mask);
}

class LocalState {
  final LocalsHandler _locals;
  final FieldInitializationScope _fields;
  bool seenReturnOrThrow = false;
  bool seenBreakOrContinue = false;
  LocalsHandler _tryBlock;

  LocalState.initial({bool inGenerativeConstructor})
      : this.internal(LocalsHandler(),
            inGenerativeConstructor ? FieldInitializationScope() : null, null,
            seenReturnOrThrow: false, seenBreakOrContinue: false);

  LocalState.childPath(LocalState other)
      : this.internal(LocalsHandler.from(other._locals),
            FieldInitializationScope.from(other._fields), other._tryBlock,
            seenReturnOrThrow: false, seenBreakOrContinue: false);

  LocalState.closure(LocalState other)
      : this.internal(LocalsHandler.from(other._locals),
            FieldInitializationScope.from(other._fields), null,
            seenReturnOrThrow: false, seenBreakOrContinue: false);

  factory LocalState.tryBlock(LocalState other, ir.TreeNode node) {
    LocalsHandler locals = LocalsHandler.tryBlock(other._locals, node);
    FieldInitializationScope fieldScope =
        FieldInitializationScope.from(other._fields);
    LocalsHandler tryBlock = locals;
    return LocalState.internal(locals, fieldScope, tryBlock,
        seenReturnOrThrow: false, seenBreakOrContinue: false);
  }

  LocalState.deepCopyOf(LocalState other)
      : _locals = LocalsHandler.deepCopyOf(other._locals),
        _tryBlock = other._tryBlock,
        _fields = other._fields;

  LocalState.internal(this._locals, this._fields, this._tryBlock,
      {this.seenReturnOrThrow, this.seenBreakOrContinue});

  bool get aborts {
    return seenReturnOrThrow || seenBreakOrContinue;
  }

  bool get isThisExposed {
    return _fields == null || _fields.isThisExposed;
  }

  void markThisAsExposed() {
    _fields?.isThisExposed = true;
  }

  void markInitializationAsIndefinite() {
    _fields?.isIndefinite = true;
  }

  TypeInformation readField(FieldEntity field) {
    return _fields.readField(field);
  }

  void updateField(FieldEntity field, TypeInformation type) {
    _fields.updateField(field, type);
  }

  TypeInformation readLocal(InferrerEngine inferrer,
      Map<Local, FieldEntity> capturedAndBoxed, Local local) {
    FieldEntity field = capturedAndBoxed[local];
    if (field != null) {
      return inferrer.typeOfMember(field);
    } else {
      return _locals.use(inferrer, local);
    }
  }

  void updateLocal(
      InferrerEngine inferrer,
      Map<Local, FieldEntity> capturedAndBoxed,
      Local local,
      TypeInformation type,
      ir.Node node,
      DartType staticType,
      {isCast = true,
      excludeNull = false}) {
    assert(type != null);
    type = inferrer.types.narrowType(type, staticType,
        isCast: isCast, excludeNull: excludeNull, excludeLateSentinel: true);

    FieldEntity field = capturedAndBoxed[local];
    if (field != null) {
      inferrer.recordTypeOfField(field, type);
    } else {
      _locals.update(inferrer, local, type, node, staticType, _tryBlock);
    }
  }

  LocalState mergeFlow(InferrerEngine inferrer, LocalState other) {
    seenReturnOrThrow = false;
    seenBreakOrContinue = false;

    if (other.aborts) {
      return this;
    }
    LocalsHandler locals = _locals.mergeFlow(inferrer, other._locals);
    return LocalState.internal(locals, _fields, _tryBlock,
        seenReturnOrThrow: seenReturnOrThrow,
        seenBreakOrContinue: seenBreakOrContinue);
  }

  LocalState mergeDiamondFlow(
      InferrerEngine inferrer, LocalState thenBranch, LocalState elseBranch) {
    seenReturnOrThrow =
        thenBranch.seenReturnOrThrow && elseBranch.seenReturnOrThrow;
    seenBreakOrContinue =
        thenBranch.seenBreakOrContinue && elseBranch.seenBreakOrContinue;

    LocalsHandler locals;
    if (aborts) {
      locals = _locals;
    } else if (thenBranch.aborts) {
      locals = _locals.mergeFlow(inferrer, elseBranch._locals, inPlace: true);
    } else if (elseBranch.aborts) {
      locals = _locals.mergeFlow(inferrer, thenBranch._locals, inPlace: true);
    } else {
      locals = _locals.mergeDiamondFlow(
          inferrer, thenBranch._locals, elseBranch._locals);
    }

    FieldInitializationScope fieldScope = _fields?.mergeDiamondFlow(
        inferrer, thenBranch._fields, elseBranch._fields);
    return LocalState.internal(locals, fieldScope, _tryBlock,
        seenReturnOrThrow: seenReturnOrThrow,
        seenBreakOrContinue: seenBreakOrContinue);
  }

  LocalState mergeAfterBreaks(InferrerEngine inferrer, List<LocalState> states,
      {bool keepOwnLocals = true}) {
    bool allBranchesAbort = true;
    for (LocalState state in states) {
      allBranchesAbort = allBranchesAbort && state.seenReturnOrThrow;
    }

    keepOwnLocals = keepOwnLocals && !seenReturnOrThrow;

    LocalsHandler locals = _locals.mergeAfterBreaks(
        inferrer,
        states
            .where((LocalState state) => !state.seenReturnOrThrow)
            .map((LocalState state) => state._locals),
        keepOwnLocals: keepOwnLocals);
    seenReturnOrThrow = allBranchesAbort && !keepOwnLocals;
    return LocalState.internal(locals, _fields, _tryBlock,
        seenReturnOrThrow: seenReturnOrThrow,
        seenBreakOrContinue: seenBreakOrContinue);
  }

  bool mergeAll(InferrerEngine inferrer, List<LocalState> states) {
    assert(!seenReturnOrThrow);
    return _locals.mergeAll(
        inferrer,
        states
            .where((LocalState state) => !state.seenReturnOrThrow)
            .map((LocalState state) => state._locals));
  }

  void startLoop(InferrerEngine inferrer, ir.Node loop) {
    _locals.startLoop(inferrer, loop);
  }

  void endLoop(InferrerEngine inferrer, ir.Node loop) {
    _locals.endLoop(inferrer, loop);
  }

  String toStructuredText(String indent) {
    StringBuffer sb = StringBuffer();
    _toStructuredText(sb, indent);
    return sb.toString();
  }

  void _toStructuredText(StringBuffer sb, String indent) {
    sb.write('LocalState($hashCode) [');
    sb.write('\n${indent}  locals:');
    sb.write(_locals.toStructuredText('${indent}    '));
    sb.write('\n]');
  }

  @override
  String toString() {
    StringBuffer sb = StringBuffer();
    sb.write('LocalState(');
    sb.write('locals=$_locals');
    if (_fields != null) {
      sb.write(',fields=$_fields');
    }
    if (seenReturnOrThrow) {
      sb.write(',seenReturnOrThrow');
    }
    if (seenBreakOrContinue) {
      sb.write(',seenBreakOrContinue');
    }
    sb.write(')');
    return sb.toString();
  }
}
