// 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 'package:kernel/class_hierarchy.dart' as ir;
import 'package:kernel/core_types.dart' as ir;
import 'package:kernel/type_algebra.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;
import '../common/names.dart';
import '../util/util.dart';
import 'runtime_type_analysis.dart';
import 'scope.dart';
import 'static_type_base.dart';
import 'static_type_cache.dart';

/// Enum values for how the target of a static type should be interpreted.
enum ClassRelation {
  /// The target is any subtype of the static type.
  subtype,

  /// The target is a subclass or mixin application of the static type.
  ///
  /// This corresponds to accessing a member through a this expression.
  thisExpression,

  /// The target is an exact instance of the static type.
  exact,
}

ClassRelation computeClassRelationFromType(ir.DartType type) {
  if (type is ThisInterfaceType) {
    return ClassRelation.thisExpression;
  } else if (type is ExactInterfaceType) {
    return ClassRelation.exact;
  } else {
    return ClassRelation.subtype;
  }
}

/// Visitor that computes and caches the static type of expression while
/// visiting the full tree at expression level.
///
/// To ensure that the traversal only visits and computes the expression type
/// for each expression once, this class performs the traversal explicitly and
/// adds 'handleX' hooks for subclasses to handle individual expressions using
/// the readily compute static types of subexpressions.
abstract class StaticTypeVisitor extends StaticTypeBase {
  final Map<ir.Expression, ir.DartType> _expressionTypeCache = {};
  Map<ir.ForInStatement, ir.DartType> _forInIteratorTypeCache;
  Map<ir.Expression, TypeMap> typeMapsForTesting;
  Map<ir.PropertyGet, RuntimeTypeUseData> _pendingRuntimeTypeUseData = {};

  final ir.ClassHierarchy hierarchy;

  ThisInterfaceType _thisType;
  ir.Library _currentLibrary;

  StaticTypeVisitor(ir.TypeEnvironment typeEnvironment, this.hierarchy)
      : super(typeEnvironment);

  StaticTypeCache getStaticTypeCache() {
    return new StaticTypeCache(_expressionTypeCache, _forInIteratorTypeCache);
  }

  /// If `true`, the effect of executing assert statements is taken into account
  /// when computing the static type.
  bool get useAsserts;

  /// If `true`, the static type of an effectively final variable is inferred
  /// from the static type of its initializer.
  bool get inferEffectivelyFinalVariableTypes;

  VariableScopeModel get variableScopeModel;

  @override
  ThisInterfaceType get thisType {
    assert(_thisType != null);
    return _thisType;
  }

  void set thisType(ThisInterfaceType value) {
    assert(value == null || _thisType == null);
    _thisType = value;
  }

  ir.Library get currentLibrary {
    assert(_currentLibrary != null);
    return _currentLibrary;
  }

  void set currentLibrary(ir.Library value) {
    assert(value == null || _currentLibrary == null);
    _currentLibrary = value;
  }

  bool completes(ir.DartType type) => type != const DoesNotCompleteType();

  Set<ir.VariableDeclaration> _currentVariables;
  Set<ir.VariableDeclaration> _invalidatedVariables =
      new Set<ir.VariableDeclaration>();

  TypeMap _typeMapBase = const TypeMap();
  TypeMap _typeMapWhenTrue;
  TypeMap _typeMapWhenFalse;

  /// Returns the local variable type promotions for when the boolean value of
  /// the most recent node is not taken into account.
  TypeMap get typeMap {
    if (_typeMapBase == null) {
      _typeMapBase = _typeMapWhenTrue.join(_typeMapWhenFalse);
      _typeMapWhenTrue = _typeMapWhenFalse = null;
    }
    return _typeMapBase;
  }

  /// Sets the local variable type promotions for when the boolean value of
  /// the most recent node is not taken into account.
  void set typeMap(TypeMap value) {
    _typeMapBase = value;
    _typeMapWhenTrue = _typeMapWhenFalse = null;
  }

  /// Returns the local variable type promotions for when the boolean value of
  /// the most recent node is `true`.
  TypeMap get typeMapWhenTrue => _typeMapWhenTrue ?? _typeMapBase;

  /// Sets the local variable type promotions for when the boolean value of
  /// the most recent node is `true`.
  void set typeMapWhenTrue(TypeMap value) {
    _typeMapWhenTrue = value;
    _typeMapBase = null;
  }

  /// Returns the local variable type promotions for when the boolean value of
  /// the most recent node is `false`.
  TypeMap get typeMapWhenFalse => _typeMapWhenFalse ?? _typeMapBase;

  /// Sets the local variable type promotions for when the boolean value of
  /// the most recent node is `false`.
  void set typeMapWhenFalse(TypeMap value) {
    _typeMapWhenFalse = value;
    _typeMapBase = null;
  }

  @override
  ir.DartType defaultNode(ir.Node node) =>
      throw UnsupportedError('Unhandled node $node (${node.runtimeType})');

  @override
  Null visitComponent(ir.Component node) {
    visitNodes(node.libraries);
  }

  @override
  Null visitLibrary(ir.Library node) {
    visitNodes(node.classes);
    visitNodes(node.procedures);
    visitNodes(node.fields);
  }

  @override
  Null visitClass(ir.Class node) {
    visitNodes(node.constructors);
    visitNodes(node.procedures);
    visitNodes(node.fields);
  }

  ir.InterfaceType getInterfaceTypeOf(ir.DartType type) {
    while (type is ir.TypeParameterType) {
      type = (type as ir.TypeParameterType).parameter.bound;
    }
    return type is ir.InterfaceType ? type : null;
  }

  /// Returns the static type of the expression as an instantiation of
  /// [superclass].
  ///
  /// Should only be used on code compiled in strong mode, as this method
  /// assumes the IR is strongly typed.
  ///
  /// This method furthermore assumes that the type of the expression actually
  /// is a subtype of (some instantiation of) the given [superclass].
  /// If this is not the case the raw type of [superclass] is returned.
  ///
  /// This method is derived from `ir.Expression.getStaticTypeAsInstanceOf`.
  ir.InterfaceType getTypeAsInstanceOf(ir.DartType type, ir.Class superclass) {
    // This method assumes the program is correctly typed, so if the superclass
    // is not generic, we can just return its raw type without computing the
    // type of this expression.  It also ensures that all types are considered
    // subtypes of Object (not just interface types), and function types are
    // considered subtypes of Function.
    if (superclass.typeParameters.isEmpty) {
      return typeEnvironment.coreTypes
          .rawType(superclass, currentLibrary.nonNullable);
    }
    while (type is ir.TypeParameterType) {
      type = (type as ir.TypeParameterType).parameter.bound;
    }
    if (type == typeEnvironment.nullType) {
      return typeEnvironment.coreTypes
          .bottomInterfaceType(superclass, currentLibrary.nullable);
    }
    if (type is ir.InterfaceType) {
      ir.InterfaceType upcastType = typeEnvironment.getTypeAsInstanceOf(
          type, superclass, currentLibrary, typeEnvironment.coreTypes);
      if (upcastType != null) return upcastType;
    } else if (type is ir.BottomType) {
      return typeEnvironment.coreTypes
          .bottomInterfaceType(superclass, currentLibrary.nonNullable);
    }
    // TODO(johnniwinther): Should we assert that this doesn't happen?
    return typeEnvironment.coreTypes
        .rawType(superclass, currentLibrary.nonNullable);
  }

  /// Computes the result type of the property access [node] on a receiver of
  /// type [receiverType].
  ///
  /// If the `node.interfaceTarget` is `null` but matches an `Object` member
  /// it is updated to target this member.
  ir.DartType _computePropertyGetType(
      ir.PropertyGet node, ir.DartType receiverType) {
    ir.Member interfaceTarget = node.interfaceTarget;
    if (interfaceTarget == null && receiverType is ir.InterfaceType) {
      interfaceTarget = node.interfaceTarget =
          hierarchy.getInterfaceMember(receiverType.classNode, node.name);
    }
    if (interfaceTarget != null) {
      ir.Class superclass = interfaceTarget.enclosingClass;
      receiverType = getTypeAsInstanceOf(receiverType, superclass);
      return ir.Substitution.fromInterfaceType(receiverType)
          .substituteType(interfaceTarget.getterType);
    }
    // Treat the properties of Object specially.
    String nameString = node.name.name;
    if (nameString == 'hashCode') {
      return typeEnvironment.coreTypes.intNonNullableRawType;
    } else if (nameString == 'runtimeType') {
      return typeEnvironment.coreTypes.typeNonNullableRawType;
    }
    return const ir.DynamicType();
  }

  void handlePropertyGet(
      ir.PropertyGet node, ir.DartType receiverType, ir.DartType resultType) {}

  void handleRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind,
      ir.DartType receiverType, ir.DartType argumentType) {}

  @override
  ir.DartType visitPropertyGet(ir.PropertyGet node) {
    ir.DartType receiverType = visitNode(node.receiver);
    ir.DartType resultType = _expressionTypeCache[node] =
        _computePropertyGetType(node, receiverType);
    receiverType = _narrowInstanceReceiver(node.interfaceTarget, receiverType);
    handlePropertyGet(node, receiverType, resultType);
    if (node.name.name == Identifiers.runtimeType_) {
      RuntimeTypeUseData data =
          computeRuntimeTypeUse(_pendingRuntimeTypeUseData, node);
      if (data.leftRuntimeTypeExpression == node) {
        // [node] is the left (or single) occurrence of `.runtimeType` so we
        // can set the static type of the receiver expression.
        data.receiverType = receiverType;
      } else {
        // [node] is the right occurrence of `.runtimeType` so we
        // can set the static type of the argument expression.
        assert(data.rightRuntimeTypeExpression == node,
            "Unexpected RuntimeTypeUseData for $node: $data");
        data.argumentType = receiverType;
      }
      if (data.isComplete) {
        /// We now have all need static types so we can remove the data from
        /// the cache and handle the runtime type use.
        _pendingRuntimeTypeUseData.remove(data.leftRuntimeTypeExpression);
        if (data.rightRuntimeTypeExpression != null) {
          _pendingRuntimeTypeUseData.remove(data.rightRuntimeTypeExpression);
        }
        handleRuntimeTypeUse(
            node, data.kind, data.receiverType, data.argumentType);
      }
    }
    return resultType;
  }

  void handlePropertySet(
      ir.PropertySet node, ir.DartType receiverType, ir.DartType valueType) {}

  @override
  ir.DartType visitPropertySet(ir.PropertySet node) {
    ir.DartType receiverType = visitNode(node.receiver);
    ir.DartType valueType = super.visitPropertySet(node);
    ir.Member interfaceTarget = node.interfaceTarget;
    if (interfaceTarget == null && receiverType is ir.InterfaceType) {
      interfaceTarget = hierarchy
          .getInterfaceMember(receiverType.classNode, node.name, setter: true);
      if (interfaceTarget != null) {
        ir.Class superclass = interfaceTarget.enclosingClass;
        ir.Substitution receiverSubstitution =
            ir.Substitution.fromInterfaceType(
                getTypeAsInstanceOf(receiverType, superclass));
        ir.DartType setterType =
            receiverSubstitution.substituteType(interfaceTarget.setterType);
        if (!typeEnvironment.isSubtypeOf(
            valueType, setterType, ir.SubtypeCheckMode.ignoringNullabilities)) {
          // We need to insert an implicit cast to preserve the invariant that
          // a property set with a known interface target is also statically
          // checked.
          ir.AsExpression implicitCast =
              new ir.AsExpression(node.value, setterType)
                ..isTypeError = true
                ..parent = node;
          node.value = implicitCast;
          // Visit the newly created as expression; the original value has
          // already been visited.
          handleAsExpression(implicitCast, valueType);
          valueType = setterType;
        }
        node.interfaceTarget = interfaceTarget;
      }
    }
    receiverType = _narrowInstanceReceiver(interfaceTarget, receiverType);
    handlePropertySet(node, receiverType, valueType);
    return valueType;
  }

  void handleDirectPropertyGet(ir.DirectPropertyGet node,
      ir.DartType receiverType, ir.DartType resultType) {}

  @override
  ir.DartType visitDirectPropertyGet(ir.DirectPropertyGet node) {
    ir.DartType receiverType = visitNode(node.receiver);
    ir.Class superclass = node.target.enclosingClass;
    receiverType = getTypeAsInstanceOf(receiverType, superclass);
    ir.DartType resultType = ir.Substitution.fromInterfaceType(receiverType)
        .substituteType(node.target.getterType);
    _expressionTypeCache[node] = resultType;
    handleDirectPropertyGet(node, receiverType, resultType);
    return resultType;
  }

  void handleDirectMethodInvocation(
      ir.DirectMethodInvocation node,
      ir.DartType receiverType,
      ArgumentTypes argumentTypes,
      ir.DartType returnType) {}

  @override
  ir.DartType visitDirectMethodInvocation(ir.DirectMethodInvocation node) {
    ir.DartType receiverType = visitNode(node.receiver);
    ArgumentTypes argumentTypes = _visitArguments(node.arguments);
    ir.DartType returnType;
    if (typeEnvironment.isSpecialCasedBinaryOperator(node.target)) {
      ir.DartType argumentType = argumentTypes.positional[0];
      returnType = typeEnvironment.getTypeOfSpecialCasedBinaryOperator(
          receiverType, argumentType);
    } else {
      ir.Class superclass = node.target.enclosingClass;
      receiverType = getTypeAsInstanceOf(receiverType, superclass);
      ir.DartType returnType = ir.Substitution.fromInterfaceType(receiverType)
          .substituteType(node.target.function.returnType);
      returnType = ir.Substitution.fromPairs(
              node.target.function.typeParameters, node.arguments.types)
          .substituteType(returnType);
    }
    _expressionTypeCache[node] = returnType;
    handleDirectMethodInvocation(node, receiverType, argumentTypes, returnType);
    return returnType;
  }

  void handleDirectPropertySet(ir.DirectPropertySet node,
      ir.DartType receiverType, ir.DartType valueType) {}

  @override
  ir.DartType visitDirectPropertySet(ir.DirectPropertySet node) {
    ir.DartType receiverType = visitNode(node.receiver);
    ir.DartType valueType = super.visitDirectPropertySet(node);
    handleDirectPropertySet(node, receiverType, valueType);
    return valueType;
  }

  /// Returns `true` if [interfaceTarget] is an arithmetic operator whose result
  /// type is computed using both the receiver type and the argument type.
  ///
  /// Visitors that subclass the [StaticTypeVisitor] must special case this
  /// target as to avoid visiting the argument twice.
  bool isSpecialCasedBinaryOperator(ir.Member interfaceTarget) {
    return interfaceTarget is ir.Procedure &&
        typeEnvironment.isSpecialCasedBinaryOperator(interfaceTarget);
  }

  ir.Member _getMember(ir.Class cls, String name) {
    for (ir.Member member in cls.members) {
      if (member.name.name == name) return member;
    }
    throw fail("Member '$name' not found in $cls");
  }

  ir.Procedure _objectEquals;
  ir.Procedure get objectEquals =>
      _objectEquals ??= _getMember(typeEnvironment.coreTypes.objectClass, '==');

  /// Returns [receiverType] narrowed to enclosing class of [interfaceTarget].
  ///
  /// If [interfaceTarget] is `null` or `receiverType` is _not_ `dynamic` no
  /// narrowing is performed.
  ir.DartType _narrowInstanceReceiver(
      ir.Member interfaceTarget, ir.DartType receiverType) {
    if (interfaceTarget != null && receiverType == const ir.DynamicType()) {
      receiverType = interfaceTarget.enclosingClass.getThisType(
          typeEnvironment.coreTypes,
          interfaceTarget.enclosingLibrary.nonNullable);
    }
    return receiverType;
  }

  /// Returns `true` if [member] can be called with the structure of
  /// [arguments].
  bool _isApplicable(ir.Arguments arguments, ir.Member member) {
    /// Returns `true` if [arguments] are applicable to the function type
    /// structure.
    bool isFunctionTypeApplicable(
        int typeParameterCount,
        int requiredParameterCount,
        int positionalParameterCount,
        Iterable<String> Function() getNamedParameters) {
      if (arguments.types.isNotEmpty &&
          arguments.types.length != typeParameterCount) {
        return false;
      }
      if (arguments.positional.length < requiredParameterCount) {
        return false;
      }
      if (arguments.positional.length > positionalParameterCount) {
        return false;
      }
      Iterable<String> namedParameters = getNamedParameters();
      if (arguments.named.length > namedParameters.length) {
        return false;
      }
      if (arguments.named.isNotEmpty) {
        for (ir.NamedExpression namedArguments in arguments.named) {
          if (!namedParameters.contains(namedArguments.name)) {
            return false;
          }
        }
      }
      return true;
    }

    /// Returns `true` if [arguments] are applicable to a value of the static
    /// [type].
    bool isTypeApplicable(ir.DartType type) {
      if (type is ir.DynamicType) return true;
      if (type == typeEnvironment.coreTypes.functionLegacyRawType ||
          type == typeEnvironment.coreTypes.functionNullableRawType ||
          type == typeEnvironment.coreTypes.functionNonNullableRawType)
        return true;
      if (type is ir.FunctionType) {
        return isFunctionTypeApplicable(
            type.typeParameters.length,
            type.requiredParameterCount,
            type.positionalParameters.length,
            () => type.namedParameters.map((p) => p.name).toSet());
      }
      return false;
    }

    if (member is ir.Procedure) {
      if (member.kind == ir.ProcedureKind.Setter ||
          member.kind == ir.ProcedureKind.Factory) {
        return false;
      } else if (member.kind == ir.ProcedureKind.Getter) {
        return isTypeApplicable(member.getterType);
      } else if (member.kind == ir.ProcedureKind.Method ||
          member.kind == ir.ProcedureKind.Operator) {
        return isFunctionTypeApplicable(
            member.function.typeParameters.length,
            member.function.requiredParameterCount,
            member.function.positionalParameters.length,
            () => member.function.namedParameters.map((p) => p.name).toSet());
      }
    } else if (member is ir.Field) {
      return isTypeApplicable(member.type);
    }
    return false;
  }

  /// Update the interface target on [node].
  ///
  /// This inserts any implicit cast of the arguments necessary to uphold the
  /// invariant that a method invocation with an interface target handles
  /// the static types at the call site.
  void _updateMethodInvocationTarget(
      ir.MethodInvocation node,
      ArgumentTypes argumentTypes,
      ir.DartType functionType,
      ir.Member interfaceTarget) {
    // TODO(johnniwinther): Handle incremental target improvement.
    if (node.interfaceTarget != null) return;
    node.interfaceTarget = interfaceTarget;
    if (functionType is! ir.FunctionType) return;
    ir.FunctionType parameterTypes = functionType;
    Map<int, ir.DartType> neededPositionalChecks = {};
    for (int i = 0; i < node.arguments.positional.length; i++) {
      ir.DartType argumentType = argumentTypes.positional[i];
      ir.DartType parameterType = parameterTypes.positionalParameters[i];
      if (!typeEnvironment.isSubtypeOf(argumentType, parameterType,
          ir.SubtypeCheckMode.ignoringNullabilities)) {
        neededPositionalChecks[i] = parameterType;
      }
    }
    Map<int, ir.DartType> neededNamedChecks = {};
    for (int argumentIndex = 0;
        argumentIndex < node.arguments.named.length;
        argumentIndex++) {
      ir.NamedExpression namedArgument = node.arguments.named[argumentIndex];
      ir.DartType argumentType = argumentTypes.named[argumentIndex];
      ir.DartType parameterType = parameterTypes.namedParameters
          .singleWhere((namedType) => namedType.name == namedArgument.name)
          .type;
      if (!typeEnvironment.isSubtypeOf(argumentType, parameterType,
          ir.SubtypeCheckMode.ignoringNullabilities)) {
        neededNamedChecks[argumentIndex] = parameterType;
      }
    }
    if (neededPositionalChecks.isEmpty && neededNamedChecks.isEmpty) {
      // No implicit casts needed
      return;
    }

    List<ir.VariableDeclaration> letVariables = [];

    // Arguments need to be hoisted to an enclosing let expression in order
    // to ensure that the arguments are evaluated before any implicit cast.

    ir.Expression updateArgument(ir.Expression expression, ir.TreeNode parent,
        ir.DartType argumentType, ir.DartType checkedParameterType) {
      ir.VariableDeclaration variable =
          new ir.VariableDeclaration.forValue(expression, type: argumentType);
      // Visit the newly created variable declaration.
      handleVariableDeclaration(variable);
      letVariables.add(variable);
      ir.VariableGet get = new ir.VariableGet(variable)..parent = parent;
      // Visit the newly created variable get.
      handleVariableGet(get, argumentType);
      _expressionTypeCache[get] = argumentType;

      if (checkedParameterType == null) {
        return get;
      }
      // We need to insert an implicit cast to preserve the invariant that
      // a method invocation with a known interface target is also
      // statically checked.
      ir.AsExpression implicitCast =
          new ir.AsExpression(get, checkedParameterType)
            ..isTypeError = true
            ..parent = parent;
      // Visit the newly created as expression; the original value has
      // already been visited.
      handleAsExpression(implicitCast, argumentType);
      return implicitCast;
    }

    for (int index = 0; index < node.arguments.positional.length; index++) {
      ir.DartType argumentType = argumentTypes.positional[index];
      node.arguments.positional[index] = updateArgument(
          node.arguments.positional[index],
          node.arguments,
          argumentType,
          neededPositionalChecks[index]);
    }
    for (int argumentIndex = 0;
        argumentIndex < node.arguments.named.length;
        argumentIndex++) {
      ir.NamedExpression namedArgument = node.arguments.named[argumentIndex];
      ir.DartType argumentType = argumentTypes.named[argumentIndex];
      namedArgument.value = updateArgument(namedArgument.value, namedArgument,
          argumentType, neededNamedChecks[argumentIndex]);
    }

    ir.Expression dummy = new ir.NullLiteral();
    node.replaceWith(dummy);
    ir.Expression body = node;
    for (ir.VariableDeclaration variable in letVariables.reversed) {
      body = new ir.Let(variable, body);
    }
    dummy.replaceWith(body);
  }

  /// Computes the result type of the method invocation [node] on a receiver of
  /// type [receiverType].
  ///
  /// If the `node.interfaceTarget` is `null` but matches an `Object` member
  /// it is updated to target this member.
  ir.DartType _computeMethodInvocationType(ir.MethodInvocation node,
      ir.DartType receiverType, ArgumentTypes argumentTypes) {
    ir.Member interfaceTarget = node.interfaceTarget;
    // TODO(34602): Remove when `interfaceTarget` is set on synthetic calls to
    // ==.
    if (interfaceTarget == null &&
        node.name.name == '==' &&
        node.arguments.types.isEmpty &&
        node.arguments.positional.length == 1 &&
        node.arguments.named.isEmpty) {
      interfaceTarget = node.interfaceTarget = objectEquals;
    }
    if (interfaceTarget == null && receiverType is ir.InterfaceType) {
      ir.Member member =
          hierarchy.getInterfaceMember(receiverType.classNode, node.name);
      if (_isApplicable(node.arguments, member)) {
        interfaceTarget = member;
      }
    }
    if (interfaceTarget != null) {
      ir.Class superclass = interfaceTarget.enclosingClass;
      ir.Substitution receiverSubstitution = ir.Substitution.fromInterfaceType(
          getTypeAsInstanceOf(receiverType, superclass));
      ir.DartType getterType =
          receiverSubstitution.substituteType(interfaceTarget.getterType);
      if (getterType is ir.FunctionType) {
        ir.FunctionType functionType = getterType;
        List<ir.DartType> typeArguments = node.arguments.types;
        if (interfaceTarget is ir.Procedure &&
            interfaceTarget.function.typeParameters.isNotEmpty &&
            typeArguments.isEmpty) {
          // If this was a dynamic call the invocation does not have the
          // inferred default type arguments so we need to create them here
          // to perform a valid substitution.
          typeArguments = interfaceTarget.function.typeParameters
              .map((t) => receiverSubstitution.substituteType(t.defaultType))
              .toList();
        }
        getterType = ir.Substitution.fromPairs(
                functionType.typeParameters, typeArguments)
            .substituteType(functionType.withoutTypeParameters);
      }
      _updateMethodInvocationTarget(
          node, argumentTypes, getterType, interfaceTarget);
      if (isSpecialCasedBinaryOperator(interfaceTarget)) {
        ir.DartType argumentType = argumentTypes.positional[0];
        return typeEnvironment.getTypeOfSpecialCasedBinaryOperator(
            receiverType, argumentType);
      } else if (getterType is ir.FunctionType) {
        return getterType.returnType;
      } else {
        return const ir.DynamicType();
      }
    }
    if (node.name.name == 'call') {
      if (receiverType is ir.FunctionType) {
        if (receiverType.typeParameters.length != node.arguments.types.length) {
          return const DoesNotCompleteType();
        }
        return ir.Substitution.fromPairs(
                receiverType.typeParameters, node.arguments.types)
            .substituteType(receiverType.returnType);
      }
    }
    if (node.name.name == '==') {
      // We use this special case to simplify generation of '==' checks.
      return typeEnvironment.coreTypes.boolNonNullableRawType;
    }
    return const ir.DynamicType();
  }

  ArgumentTypes _visitArguments(ir.Arguments arguments) {
    List<ir.DartType> positional;
    List<ir.DartType> named;
    if (arguments.positional.isEmpty) {
      positional = const <ir.DartType>[];
    } else {
      positional = new List<ir.DartType>(arguments.positional.length);
      int index = 0;
      for (ir.Expression argument in arguments.positional) {
        positional[index++] = visitNode(argument);
      }
    }
    if (arguments.named.isEmpty) {
      named = const <ir.DartType>[];
    } else {
      named = new List<ir.DartType>(arguments.named.length);
      int index = 0;
      for (ir.NamedExpression argument in arguments.named) {
        named[index++] = visitNode(argument);
      }
    }
    return new ArgumentTypes(positional, named);
  }

  void handleMethodInvocation(
      ir.MethodInvocation node,
      ir.DartType receiverType,
      ArgumentTypes argumentTypes,
      ir.DartType returnType) {}

  @override
  ir.DartType visitMethodInvocation(ir.MethodInvocation node) {
    ArgumentTypes argumentTypes = _visitArguments(node.arguments);
    ir.DartType receiverType = visitNode(node.receiver);
    ir.DartType returnType =
        _computeMethodInvocationType(node, receiverType, argumentTypes);
    receiverType = _narrowInstanceReceiver(node.interfaceTarget, receiverType);
    if (node.name.name == '==') {
      ir.Expression left = node.receiver;
      ir.Expression right = node.arguments.positional[0];
      TypeMap afterInvocation = typeMap;
      if (left is ir.VariableGet &&
          right is ir.NullLiteral &&
          !_invalidatedVariables.contains(left.variable)) {
        // If `left == null` is true, we promote the type of the variable to
        // `Null` by registering that is known _not_ to be of its declared type.
        typeMapWhenTrue = afterInvocation
            .promote(left.variable, left.variable.type, isTrue: false);
        typeMapWhenFalse = afterInvocation
            .promote(left.variable, left.variable.type, isTrue: true);
      }
      if (right is ir.VariableGet &&
          left is ir.NullLiteral &&
          !_invalidatedVariables.contains(right.variable)) {
        // If `null == right` is true, we promote the type of the variable to
        // `Null` by registering that is known _not_ to be of its declared type.
        typeMapWhenTrue = afterInvocation
            .promote(right.variable, right.variable.type, isTrue: false);
        typeMapWhenFalse = afterInvocation
            .promote(right.variable, right.variable.type, isTrue: true);
      }
    }
    _expressionTypeCache[node] = returnType;
    handleMethodInvocation(node, receiverType, argumentTypes, returnType);
    return returnType;
  }

  void handleVariableGet(ir.VariableGet node, ir.DartType type) {}

  @override
  ir.DartType visitVariableGet(ir.VariableGet node) {
    if (typeMapsForTesting != null) {
      typeMapsForTesting[node] = typeMap;
    }
    ir.DartType promotedType = typeMap.typeOf(node, typeEnvironment);
    assert(
        node.promotedType == null ||
            promotedType == typeEnvironment.nullType ||
            promotedType is ir.FutureOrType ||
            typeEnvironment.isSubtypeOf(promotedType, node.promotedType,
                ir.SubtypeCheckMode.ignoringNullabilities),
        "Unexpected promotion of ${node.variable} in ${node.parent}. "
        "Expected ${node.promotedType}, found $promotedType");
    _expressionTypeCache[node] = promotedType;
    handleVariableGet(node, promotedType);
    return promotedType;
  }

  void handleVariableSet(ir.VariableSet node, ir.DartType resultType) {}

  @override
  ir.DartType visitVariableSet(ir.VariableSet node) {
    ir.DartType resultType = super.visitVariableSet(node);
    handleVariableSet(node, resultType);
    if (!_currentVariables.contains(node.variable)) {
      _invalidatedVariables.add(node.variable);
      typeMap = typeMap.remove([node.variable]);
    } else {
      typeMap = typeMap.reduce(node, resultType, typeEnvironment);
    }
    return resultType;
  }

  void handleStaticGet(ir.StaticGet node, ir.DartType resultType) {}

  @override
  ir.DartType visitStaticGet(ir.StaticGet node) {
    ir.DartType resultType = super.visitStaticGet(node);
    handleStaticGet(node, resultType);
    return resultType;
  }

  void handleStaticSet(ir.StaticSet node, ir.DartType valueType) {}

  @override
  ir.DartType visitStaticSet(ir.StaticSet node) {
    ir.DartType valueType = super.visitStaticSet(node);
    handleStaticSet(node, valueType);
    return valueType;
  }

  void handleStaticInvocation(ir.StaticInvocation node,
      ArgumentTypes argumentTypes, ir.DartType returnType) {}

  @override
  ir.DartType visitStaticInvocation(ir.StaticInvocation node) {
    ArgumentTypes argumentTypes = _visitArguments(node.arguments);
    ir.DartType returnType = ir.Substitution.fromPairs(
            node.target.function.typeParameters, node.arguments.types)
        .substituteType(node.target.function.returnType);
    _expressionTypeCache[node] = returnType;
    handleStaticInvocation(node, argumentTypes, returnType);
    return returnType;
  }

  void handleConstructorInvocation(ir.ConstructorInvocation node,
      ArgumentTypes argumentTypes, ir.DartType resultType) {}

  @override
  ir.DartType visitConstructorInvocation(ir.ConstructorInvocation node) {
    ArgumentTypes argumentTypes = _visitArguments(node.arguments);
    ir.DartType resultType = node.arguments.types.isEmpty
        ? new ExactInterfaceType.from(typeEnvironment.coreTypes
            .nonNullableRawType(node.target.enclosingClass))
        : new ExactInterfaceType(node.target.enclosingClass,
            ir.Nullability.nonNullable, node.arguments.types);
    _expressionTypeCache[node] = resultType;
    handleConstructorInvocation(node, argumentTypes, resultType);
    return resultType;
  }

  void handleSuperPropertyGet(
      ir.SuperPropertyGet node, ir.DartType resultType) {}

  @override
  ir.DartType visitSuperPropertyGet(ir.SuperPropertyGet node) {
    ir.DartType resultType;
    if (node.interfaceTarget == null) {
      // TODO(johnniwinther): Resolve and set the target here.
      resultType = const ir.DynamicType();
    } else {
      ir.Class declaringClass = node.interfaceTarget.enclosingClass;
      if (declaringClass.typeParameters.isEmpty) {
        resultType = node.interfaceTarget.getterType;
      } else {
        ir.DartType receiver = typeEnvironment.getTypeAsInstanceOf(thisType,
            declaringClass, currentLibrary, typeEnvironment.coreTypes);
        resultType = ir.Substitution.fromInterfaceType(receiver)
            .substituteType(node.interfaceTarget.getterType);
      }
    }
    _expressionTypeCache[node] = resultType;
    handleSuperPropertyGet(node, resultType);
    return resultType;
  }

  void handleSuperPropertySet(
      ir.SuperPropertySet node, ir.DartType valueType) {}

  @override
  ir.DartType visitSuperPropertySet(ir.SuperPropertySet node) {
    ir.DartType valueType = super.visitSuperPropertySet(node);
    handleSuperPropertySet(node, valueType);
    return valueType;
  }

  void handleSuperMethodInvocation(ir.SuperMethodInvocation node,
      ArgumentTypes argumentTypes, ir.DartType returnType) {}

  @override
  ir.DartType visitSuperMethodInvocation(ir.SuperMethodInvocation node) {
    ArgumentTypes argumentTypes = _visitArguments(node.arguments);
    ir.DartType returnType;
    if (node.interfaceTarget == null) {
      // TODO(johnniwinther): Resolve and set the target here.
      returnType = const ir.DynamicType();
    } else {
      ir.Class superclass = node.interfaceTarget.enclosingClass;
      ir.InterfaceType receiverType = typeEnvironment.getTypeAsInstanceOf(
          thisType, superclass, currentLibrary, typeEnvironment.coreTypes);
      returnType = ir.Substitution.fromInterfaceType(receiverType)
          .substituteType(node.interfaceTarget.function.returnType);
      returnType = ir.Substitution.fromPairs(
              node.interfaceTarget.function.typeParameters,
              node.arguments.types)
          .substituteType(returnType);
    }
    _expressionTypeCache[node] = returnType;
    handleSuperMethodInvocation(node, argumentTypes, returnType);
    return returnType;
  }

  @override
  ir.DartType visitLogicalExpression(ir.LogicalExpression node) {
    if (node.operator == '&&') {
      visitNode(node.left);
      TypeMap afterLeftWhenTrue = typeMapWhenTrue;
      TypeMap afterLeftWhenFalse = typeMapWhenFalse;
      typeMap = afterLeftWhenTrue;
      visitNode(node.right);
      TypeMap afterRightWhenTrue = typeMapWhenTrue;
      TypeMap afterRightWhenFalse = typeMapWhenFalse;
      typeMapWhenTrue = afterRightWhenTrue;
      typeMapWhenFalse = afterLeftWhenFalse.join(afterRightWhenFalse);
    } else {
      visitNode(node.left);
      TypeMap afterLeftWhenTrue = typeMapWhenTrue;
      TypeMap afterLeftWhenFalse = typeMapWhenFalse;
      typeMap = afterLeftWhenFalse;
      visitNode(node.right);
      TypeMap afterRightWhenTrue = typeMapWhenTrue;
      TypeMap afterRightWhenFalse = typeMapWhenFalse;
      typeMapWhenTrue = afterLeftWhenTrue.join(afterRightWhenTrue);
      typeMapWhenFalse = afterRightWhenFalse;
    }
    return super.visitLogicalExpression(node);
  }

  @override
  ir.DartType visitNot(ir.Not node) {
    visitNode(node.operand);
    TypeMap afterOperandWhenTrue = typeMapWhenTrue;
    TypeMap afterOperandWhenFalse = typeMapWhenFalse;
    typeMapWhenTrue = afterOperandWhenFalse;
    typeMapWhenFalse = afterOperandWhenTrue;
    return super.visitNot(node);
  }

  ir.DartType _handleConditional(
      ir.Expression condition, ir.TreeNode then, ir.TreeNode otherwise) {
    visitNode(condition);
    TypeMap afterConditionWhenTrue = typeMapWhenTrue;
    TypeMap afterConditionWhenFalse = typeMapWhenFalse;
    typeMap = afterConditionWhenTrue;
    ir.DartType thenType = visitNode(then);
    TypeMap afterThen = typeMap;
    typeMap = afterConditionWhenFalse;
    ir.DartType otherwiseType = visitNode(otherwise);
    TypeMap afterOtherwise = typeMap;
    if (completes(thenType) && completes(otherwiseType)) {
      typeMap = afterThen.join(afterOtherwise);
      return null;
    } else if (completes(thenType)) {
      typeMap = afterThen;
      return null;
    } else if (completes(otherwiseType)) {
      typeMap = afterOtherwise;
      return null;
    } else {
      typeMap = afterThen.join(afterOtherwise);
      return const DoesNotCompleteType();
    }
  }

  @override
  ir.DartType visitConditionalExpression(ir.ConditionalExpression node) {
    // TODO(johnniwinther): Should we return `const DoesNotCompleteType()` if
    // both branches are failing?
    _handleConditional(node.condition, node.then, node.otherwise);
    return super.visitConditionalExpression(node);
  }

  void handleIsExpression(ir.IsExpression node) {}

  @override
  ir.DartType visitIsExpression(ir.IsExpression node) {
    ir.Expression operand = node.operand;
    visitNode(operand);
    if (operand is ir.VariableGet &&
        !_invalidatedVariables.contains(operand.variable)) {
      TypeMap afterOperand = typeMap;
      typeMapWhenTrue =
          afterOperand.promote(operand.variable, node.type, isTrue: true);
      typeMapWhenFalse =
          afterOperand.promote(operand.variable, node.type, isTrue: false);
    }
    handleIsExpression(node);
    return super.visitIsExpression(node);
  }

  @override
  ir.DartType visitLet(ir.Let node) {
    _processLocalVariable(node.variable);
    return super.visitLet(node);
  }

  @override
  ir.DartType visitBlockExpression(ir.BlockExpression node) {
    visitNode(node.body);
    return super.visitBlockExpression(node);
  }

  ir.DartType _computeInstantiationType(
      ir.Instantiation node, ir.FunctionType expressionType) {
    return ir.Substitution.fromPairs(
            expressionType.typeParameters, node.typeArguments)
        .substituteType(expressionType.withoutTypeParameters);
  }

  void handleInstantiation(ir.Instantiation node,
      ir.FunctionType expressionType, ir.DartType resultType) {}

  @override
  ir.DartType visitInstantiation(ir.Instantiation node) {
    ir.FunctionType expressionType = visitNode(node.expression);
    ir.DartType resultType = _computeInstantiationType(node, expressionType);
    _expressionTypeCache[node] = resultType;
    handleInstantiation(node, expressionType, resultType);
    return resultType;
  }

  @override
  ir.DartType visitBlock(ir.Block node) {
    assert(_pendingRuntimeTypeUseData.isEmpty);
    ir.DartType type;
    for (ir.Statement statement in node.statements) {
      if (!completes(visitNode(statement))) {
        type = const DoesNotCompleteType();
      }
    }
    assert(_pendingRuntimeTypeUseData.isEmpty,
        "Incomplete RuntimeTypeUseData: $_pendingRuntimeTypeUseData");
    return type;
  }

  @override
  ir.DartType visitExpressionStatement(ir.ExpressionStatement node) {
    if (completes(visitNode(node.expression))) {
      return null;
    } else {
      return const DoesNotCompleteType();
    }
  }

  void handleAsExpression(ir.AsExpression node, ir.DartType operandType) {}

  @override
  ir.DartType visitAsExpression(ir.AsExpression node) {
    ir.DartType operandType = visitNode(node.operand);
    handleAsExpression(node, operandType);
    return super.visitAsExpression(node);
  }

  void handleNullCheck(ir.NullCheck node, ir.DartType operandType) {}

  @override
  ir.DartType visitNullCheck(ir.NullCheck node) {
    ir.DartType operandType = visitNode(node.operand);
    handleNullCheck(node, operandType);
    ir.DartType resultType = operandType == typeEnvironment.nullType
        ? const ir.NeverType(ir.Nullability.nonNullable)
        : operandType.withDeclaredNullability(ir.Nullability.nonNullable);
    _expressionTypeCache[node] = resultType;
    return resultType;
  }

  void handleStringConcatenation(ir.StringConcatenation node) {}

  @override
  ir.DartType visitStringConcatenation(ir.StringConcatenation node) {
    visitNodes(node.expressions);
    handleStringConcatenation(node);
    return super.visitStringConcatenation(node);
  }

  void handleIntLiteral(ir.IntLiteral node) {}

  @override
  ir.DartType visitIntLiteral(ir.IntLiteral node) {
    handleIntLiteral(node);
    return super.visitIntLiteral(node);
  }

  void handleDoubleLiteral(ir.DoubleLiteral node) {}

  @override
  ir.DartType visitDoubleLiteral(ir.DoubleLiteral node) {
    handleDoubleLiteral(node);
    return super.visitDoubleLiteral(node);
  }

  void handleBoolLiteral(ir.BoolLiteral node) {}

  @override
  ir.DartType visitBoolLiteral(ir.BoolLiteral node) {
    handleBoolLiteral(node);
    return super.visitBoolLiteral(node);
  }

  void handleStringLiteral(ir.StringLiteral node) {}

  @override
  ir.DartType visitStringLiteral(ir.StringLiteral node) {
    handleStringLiteral(node);
    return super.visitStringLiteral(node);
  }

  void handleSymbolLiteral(ir.SymbolLiteral node) {}

  @override
  ir.DartType visitSymbolLiteral(ir.SymbolLiteral node) {
    handleSymbolLiteral(node);
    return super.visitSymbolLiteral(node);
  }

  void handleNullLiteral(ir.NullLiteral node) {}

  @override
  ir.DartType visitNullLiteral(ir.NullLiteral node) {
    handleNullLiteral(node);
    return super.visitNullLiteral(node);
  }

  void handleListLiteral(ir.ListLiteral node) {}

  @override
  ir.DartType visitListLiteral(ir.ListLiteral node) {
    visitNodes(node.expressions);
    handleListLiteral(node);
    return super.visitListLiteral(node);
  }

  void handleSetLiteral(ir.SetLiteral node) {}

  @override
  ir.DartType visitSetLiteral(ir.SetLiteral node) {
    visitNodes(node.expressions);
    handleSetLiteral(node);
    return super.visitSetLiteral(node);
  }

  void handleMapLiteral(ir.MapLiteral node) {}

  @override
  ir.DartType visitMapLiteral(ir.MapLiteral node) {
    visitNodes(node.entries);
    handleMapLiteral(node);
    return super.visitMapLiteral(node);
  }

  @override
  Null visitMapEntry(ir.MapEntry entry) {
    visitNode(entry.key);
    visitNode(entry.value);
  }

  void handleFunctionExpression(ir.FunctionExpression node) {}

  @override
  ir.DartType visitFunctionExpression(ir.FunctionExpression node) {
    TypeMap beforeClosure =
        typeMap.remove(variableScopeModel.getScopeFor(node).assignedVariables);
    typeMap = typeMap.remove(variableScopeModel.assignedVariables);
    ir.DartType returnType = super.visitFunctionExpression(node);
    Set<ir.VariableDeclaration> _oldVariables = _currentVariables;
    _currentVariables = {};
    visitSignature(node.function);
    visitNode(node.function.body);
    handleFunctionExpression(node);
    _invalidatedVariables.removeAll(_currentVariables);
    _currentVariables = _oldVariables;
    typeMap = beforeClosure;
    return returnType;
  }

  void handleThrow(ir.Throw node) {}

  @override
  ir.DartType visitThrow(ir.Throw node) {
    visitNode(node.expression);
    handleThrow(node);
    return super.visitThrow(node);
  }

  @override
  Null visitSwitchCase(ir.SwitchCase node) {
    visitNodes(node.expressions);
    visitNode(node.body);
  }

  @override
  ir.DartType visitContinueSwitchStatement(ir.ContinueSwitchStatement node) {
    return const DoesNotCompleteType();
  }

  @override
  Null visitLabeledStatement(ir.LabeledStatement node) {
    visitNode(node.body);
  }

  @override
  ir.DartType visitBreakStatement(ir.BreakStatement node) {
    return const DoesNotCompleteType();
  }

  @override
  Null visitYieldStatement(ir.YieldStatement node) {
    visitNode(node.expression);
  }

  @override
  Null visitAssertInitializer(ir.AssertInitializer node) {
    visitNode(node.statement);
  }

  void handleFieldInitializer(ir.FieldInitializer node) {}

  @override
  Null visitFieldInitializer(ir.FieldInitializer node) {
    visitNode(node.value);
    handleFieldInitializer(node);
  }

  void handleRedirectingInitializer(
      ir.RedirectingInitializer node, ArgumentTypes argumentTypes) {}

  @override
  Null visitRedirectingInitializer(ir.RedirectingInitializer node) {
    ArgumentTypes argumentTypes = _visitArguments(node.arguments);
    handleRedirectingInitializer(node, argumentTypes);
  }

  void handleSuperInitializer(
      ir.SuperInitializer node, ArgumentTypes argumentTypes) {}

  @override
  Null visitSuperInitializer(ir.SuperInitializer node) {
    ArgumentTypes argumentTypes = _visitArguments(node.arguments);
    handleSuperInitializer(node, argumentTypes);
  }

  @override
  Null visitLocalInitializer(ir.LocalInitializer node) {
    visitNode(node.variable);
  }

  @override
  ir.DartType visitNamedExpression(ir.NamedExpression node) =>
      visitNode(node.value);

  @override
  Null visitEmptyStatement(ir.EmptyStatement node) {}

  @override
  Null visitForStatement(ir.ForStatement node) {
    visitNodes(node.variables);
    TypeMap beforeLoop = typeMap =
        typeMap.remove(variableScopeModel.getScopeFor(node).assignedVariables);
    visitNode(node.condition);
    typeMap = typeMapWhenTrue;
    visitNode(node.body);
    visitNodes(node.updates);
    typeMap = beforeLoop;
  }

  void handleForInStatement(ir.ForInStatement node, ir.DartType iterableType,
      ir.DartType iteratorType) {}

  @override
  Null visitForInStatement(ir.ForInStatement node) {
    // For sync for-in [iterableType] is a subtype of `Iterable`, for async
    // for-in [iterableType] is a subtype of `Stream`.
    ir.DartType iterableType = visitNode(node.iterable);
    ir.DartType iteratorType = const ir.DynamicType();
    if (node.isAsync) {
      ir.InterfaceType streamInterfaceType = getInterfaceTypeOf(iterableType);
      ir.InterfaceType streamType = typeEnvironment.getTypeAsInstanceOf(
          streamInterfaceType,
          typeEnvironment.coreTypes.streamClass,
          currentLibrary,
          typeEnvironment.coreTypes);
      if (streamType != null) {
        iteratorType = new ir.InterfaceType(
            typeEnvironment.coreTypes.streamIteratorClass,
            ir.Nullability.nonNullable,
            streamType.typeArguments);
      }
    } else {
      ir.InterfaceType iterableInterfaceType = getInterfaceTypeOf(iterableType);
      ir.Member member = hierarchy.getInterfaceMember(
          iterableInterfaceType.classNode, new ir.Name(Identifiers.iterator));
      if (member != null) {
        iteratorType = ir.Substitution.fromInterfaceType(
                typeEnvironment.getTypeAsInstanceOf(
                    iterableInterfaceType,
                    member.enclosingClass,
                    currentLibrary,
                    typeEnvironment.coreTypes))
            .substituteType(member.getterType);
      }
    }
    _forInIteratorTypeCache ??= {};
    _forInIteratorTypeCache[node] = iteratorType;
    TypeMap beforeLoop = typeMap =
        typeMap.remove(variableScopeModel.getScopeFor(node).assignedVariables);
    visitNode(node.variable);
    visitNode(node.body);
    handleForInStatement(node, iterableType, iteratorType);
    typeMap = beforeLoop;
  }

  @override
  Null visitDoStatement(ir.DoStatement node) {
    TypeMap beforeLoop = typeMap =
        typeMap.remove(variableScopeModel.getScopeFor(node).assignedVariables);
    visitNode(node.body);
    visitNode(node.condition);
    typeMap = beforeLoop;
  }

  @override
  Null visitWhileStatement(ir.WhileStatement node) {
    TypeMap beforeLoop = typeMap =
        typeMap.remove(variableScopeModel.getScopeFor(node).assignedVariables);
    visitNode(node.condition);
    typeMap = typeMapWhenTrue;
    visitNode(node.body);
    typeMap = beforeLoop;
  }

  void handleSwitchStatement(ir.SwitchStatement node) {}

  @override
  Null visitSwitchStatement(ir.SwitchStatement node) {
    visitNode(node.expression);
    TypeMap afterExpression = typeMap;
    VariableScope scope = variableScopeModel.getScopeFor(node);
    TypeMap afterStatement = afterExpression.remove(scope.assignedVariables);
    TypeMap beforeCase =
        scope.hasContinueSwitch ? afterStatement : afterExpression;
    for (ir.SwitchCase switchCase in node.cases) {
      typeMap = beforeCase;
      visitNode(switchCase);
    }
    handleSwitchStatement(node);
    typeMap = afterStatement;
  }

  @override
  ir.DartType visitReturnStatement(ir.ReturnStatement node) {
    visitNode(node.expression);
    return const DoesNotCompleteType();
  }

  @override
  ir.DartType visitIfStatement(ir.IfStatement node) {
    return _handleConditional(node.condition, node.then, node.otherwise);
  }

  @override
  Null visitTryCatch(ir.TryCatch node) {
    visitNode(node.body);
    visitNodes(node.catches);
  }

  void handleCatch(ir.Catch node) {}

  @override
  Null visitCatch(ir.Catch node) {
    handleCatch(node);
    visitNode(node.body);
  }

  @override
  Null visitTryFinally(ir.TryFinally node) {
    visitNode(node.body);
    visitNode(node.finalizer);
  }

  void handleTypeLiteral(ir.TypeLiteral node) {}

  @override
  ir.DartType visitTypeLiteral(ir.TypeLiteral node) {
    handleTypeLiteral(node);
    return super.visitTypeLiteral(node);
  }

  void handleLoadLibrary(ir.LoadLibrary node) {}

  @override
  ir.DartType visitLoadLibrary(ir.LoadLibrary node) {
    handleLoadLibrary(node);
    return super.visitLoadLibrary(node);
  }

  void handleAssertStatement(ir.AssertStatement node) {}

  @override
  Null visitAssertStatement(ir.AssertStatement node) {
    TypeMap beforeCondition = typeMap;
    visitNode(node.condition);
    TypeMap afterConditionWhenTrue = typeMapWhenTrue;
    TypeMap afterConditionWhenFalse = typeMapWhenFalse;
    typeMap = afterConditionWhenFalse;
    visitNode(node.message);
    handleAssertStatement(node);
    typeMap = useAsserts ? afterConditionWhenTrue : beforeCondition;
  }

  void handleFunctionDeclaration(ir.FunctionDeclaration node) {}

  @override
  Null visitFunctionDeclaration(ir.FunctionDeclaration node) {
    TypeMap beforeClosure =
        typeMap.remove(variableScopeModel.getScopeFor(node).assignedVariables);
    typeMap = typeMap.remove(variableScopeModel.assignedVariables);
    Set<ir.VariableDeclaration> _oldVariables = _currentVariables;
    _currentVariables = {};
    visitSignature(node.function);
    visitNode(node.function.body);
    handleFunctionDeclaration(node);
    _invalidatedVariables.removeAll(_currentVariables);
    _currentVariables = _oldVariables;
    typeMap = beforeClosure;
  }

  void handleParameter(ir.VariableDeclaration node) {}

  void visitParameter(ir.VariableDeclaration node) {
    _currentVariables.add(node);
    visitNode(node.initializer);
    handleParameter(node);
  }

  void handleSignature(ir.FunctionNode node) {}

  void visitSignature(ir.FunctionNode node) {
    node.positionalParameters.forEach(visitParameter);
    node.namedParameters.forEach(visitParameter);
    handleSignature(node);
  }

  void handleProcedure(ir.Procedure node) {}

  @override
  Null visitProcedure(ir.Procedure node) {
    thisType = new ThisInterfaceType.from(node.enclosingClass?.getThisType(
        typeEnvironment.coreTypes, node.enclosingLibrary.nonNullable));
    _currentVariables = {};
    currentLibrary = node.enclosingLibrary;
    visitSignature(node.function);
    visitNode(node.function.body);
    handleProcedure(node);
    _invalidatedVariables.removeAll(_currentVariables);
    _currentVariables = null;
    thisType = null;
    currentLibrary = null;
  }

  void handleConstructor(ir.Constructor node) {}

  @override
  Null visitConstructor(ir.Constructor node) {
    thisType = new ThisInterfaceType.from(node.enclosingClass.getThisType(
        typeEnvironment.coreTypes, node.enclosingLibrary.nonNullable));
    _currentVariables = {};
    currentLibrary = node.enclosingLibrary;
    visitSignature(node.function);
    visitNodes(node.initializers);
    visitNode(node.function.body);
    handleConstructor(node);
    _invalidatedVariables.removeAll(_currentVariables);
    _currentVariables = null;
    thisType = null;
    currentLibrary = null;
  }

  void handleField(ir.Field node) {}

  @override
  Null visitField(ir.Field node) {
    thisType = new ThisInterfaceType.from(node.enclosingClass?.getThisType(
        typeEnvironment.coreTypes, node.enclosingLibrary.nonNullable));
    _currentVariables = {};
    currentLibrary = node.enclosingLibrary;
    visitNode(node.initializer);
    handleField(node);
    _invalidatedVariables.removeAll(_currentVariables);
    _currentVariables = null;
    thisType = null;
    currentLibrary = null;
  }

  void handleVariableDeclaration(ir.VariableDeclaration node) {}

  void _processLocalVariable(ir.VariableDeclaration node) {
    _currentVariables.add(node);
    ir.DartType type = visitNode(node.initializer);
    if (node.initializer != null &&
        variableScopeModel.isEffectivelyFinal(node) &&
        inferEffectivelyFinalVariableTypes) {
      node.type = type;
    }
  }

  @override
  Null visitVariableDeclaration(ir.VariableDeclaration node) {
    _processLocalVariable(node);
    handleVariableDeclaration(node);
  }

  void handleConstantExpression(ir.ConstantExpression node) {}

  @override
  ir.DartType visitConstantExpression(ir.ConstantExpression node) {
    handleConstantExpression(node);
    return super.visitConstantExpression(node);
  }
}

class ArgumentTypes {
  final List<ir.DartType> positional;
  final List<ir.DartType> named;

  ArgumentTypes(this.positional, this.named);
}

/// Type information collected for a single path for a local variable.
///
/// This is used to implement guarded type promotion.
///
/// The terminology and implementation is based on this paper:
///
///   http://www.cs.williams.edu/FTfJP2011/6-Winther.pdf
///
class TypeHolder {
  /// The declared type of the local variable.
  final ir.DartType declaredType;

  /// The types that the local variable is known to be an instance of.
  final Set<ir.DartType> trueTypes;

  /// The types that the local variable is known _not_ to be an instance of.
  final Set<ir.DartType> falseTypes;

  int _hashCode;

  TypeHolder(this.declaredType, this.trueTypes, this.falseTypes);

  /// Computes a single type that soundly represents the promoted type of the
  /// local variable on this single path.
  ir.DartType typeOf(ir.TypeEnvironment typeEnvironment) {
    ir.DartType candidate = declaredType;
    if (falseTypes != null) {
      // TODO(johnniwinther): Special-case the `== null` representation to
      // make it faster.
      for (ir.DartType type in falseTypes) {
        if (typeEnvironment.isSubtypeOf(
            declaredType, type, ir.SubtypeCheckMode.ignoringNullabilities)) {
          return typeEnvironment.nullType;
        }
      }
    }
    if (trueTypes != null) {
      for (ir.DartType type in trueTypes) {
        if (type == typeEnvironment.nullType) {
          return type;
        }
        if (typeEnvironment.isSubtypeOf(
            type, candidate, ir.SubtypeCheckMode.ignoringNullabilities)) {
          candidate = type;
        } else if (!typeEnvironment.isSubtypeOf(
            candidate, type, ir.SubtypeCheckMode.ignoringNullabilities)) {
          // We cannot promote. No single type is most specific.
          // TODO(johnniwinther): Compute implied types? For instance when the
          // declared type is `Iterable<String>` and tested type is
          // `List<dynamic>` we could promote to the implied type
          // `List<String>`.
          return null;
        }
      }
    }
    return candidate;
  }

  @override
  int get hashCode {
    if (_hashCode == null) {
      _hashCode = Hashing.setHash(falseTypes,
          Hashing.setHash(trueTypes, Hashing.objectHash(declaredType)));
    }
    return _hashCode;
  }

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    return other is TypeHolder &&
        declaredType == other.declaredType &&
        equalSets(trueTypes, other.trueTypes) &&
        equalSets(falseTypes, other.falseTypes);
  }

  void _getText(
      StringBuffer sb, String Function(Iterable<ir.DartType>) typesToText) {
    sb.write('{');
    String comma = '';
    if (trueTypes != null) {
      sb.write('true:');
      sb.write(typesToText(trueTypes));
      comma = ',';
    }
    if (falseTypes != null) {
      sb.write(comma);
      sb.write('false:');
      sb.write(typesToText(falseTypes));
    }
    sb.write('}');
  }

  @override
  String toString() {
    StringBuffer sb = new StringBuffer();
    sb.write('TypeHolder(');
    sb.write('declared=$declaredType');
    if (trueTypes != null) {
      sb.write(',true=$trueTypes');
    }
    if (falseTypes != null) {
      sb.write(',false=$falseTypes');
    }
    sb.write(')');
    return sb.toString();
  }
}

/// Type information for a single local variable on all possible paths.
///
/// This is used to implement guarded type promotion.
///
/// The terminology and implementation is based on this paper:
///
///   http://www.cs.williams.edu/FTfJP2011/6-Winther.pdf
///
class TargetInfo {
  /// The declared type of the local variable.
  final ir.DartType declaredType;

  /// Collected type information for disjoint paths.
  final Iterable<TypeHolder> typeHolders;

  /// Types relevant for promotion of the local variable.
  final Iterable<ir.DartType> typesOfInterest;

  TargetInfo(this.declaredType, this.typeHolders, this.typesOfInterest);

  /// Returns the [TargetInfo] that describes the added type knowledge for the
  /// local variable. If [isTrue] is `true`, the local variable is known to
  /// be an instance of [type]. If [isTrue] is `false`, the local variable is
  /// known _not_ to be an instance of [type].
  TargetInfo promote(ir.DartType type, {bool isTrue}) {
    Set<TypeHolder> newTypeHolders = new Set<TypeHolder>();

    bool addTypeHolder(TypeHolder typeHolder) {
      bool changed = false;

      Set<ir.DartType> addAsCopy(Set<ir.DartType> set, ir.DartType type) {
        Set<ir.DartType> result;
        if (set == null) {
          result = new Set<ir.DartType>();
        } else if (set.contains(type)) {
          return set;
        } else {
          result = Set<ir.DartType>.from(set);
        }
        changed = true;
        return result..add(type);
      }

      Set<ir.DartType> trueTypes = typeHolder?.trueTypes;
      Set<ir.DartType> falseTypes = typeHolder?.falseTypes;
      if (isTrue) {
        trueTypes = addAsCopy(trueTypes, type);
      } else {
        falseTypes = addAsCopy(falseTypes, type);
      }
      // TODO(johnniwinther): Check validity; if the true types are
      // contradicting, for instance if the local is known to be and instance
      // of types `int` and `String` simultaneously, then we could flag code
      // as dead code.
      newTypeHolders.add(TypeHolder(declaredType, trueTypes, falseTypes));
      return changed;
    }

    bool changed = false;
    if (typeHolders.isEmpty) {
      changed |= addTypeHolder(null);
    } else {
      for (TypeHolder typeHolder in typeHolders) {
        changed |= addTypeHolder(typeHolder);
      }
    }
    Iterable<ir.DartType> newTypesOfInterest;
    if (typesOfInterest.contains(type)) {
      newTypesOfInterest = typesOfInterest;
    } else {
      newTypesOfInterest = new Set<ir.DartType>.from(typesOfInterest)
        ..add(type);
      changed = true;
    }
    return changed
        ? new TargetInfo(declaredType, newTypeHolders, newTypesOfInterest)
        : this;
  }

  /// Returns the [TargetInfo] that describes that the local is either of [this]
  /// or the [other] type.
  ///
  /// Returns `null` if the join is empty.
  TargetInfo join(TargetInfo other) {
    if (other == null) return null;
    if (identical(this, other)) return this;

    Set<TypeHolder> newTypeHolders = new Set<TypeHolder>();
    Set<ir.DartType> newTypesOfInterest = new Set<ir.DartType>();

    /// Adds the [typeHolders] to [newTypeHolders] for types in
    /// [otherTypesOfInterest] while removing the information
    /// invalidated by [otherTrueTypes] and [otherFalseTypes].
    void addTypeHolders(
        Iterable<TypeHolder> typeHolders,
        Set<ir.DartType> otherTrueTypes,
        Set<ir.DartType> otherFalseTypes,
        Iterable<ir.DartType> otherTypesOfInterest) {
      for (TypeHolder typeHolder in typeHolders) {
        Set<ir.DartType> newTrueTypes;
        if (typeHolder.trueTypes != null) {
          newTrueTypes = new Set<ir.DartType>.from(typeHolder.trueTypes);

          /// Only types in [otherTypesOfInterest] has information from all
          /// paths.
          newTrueTypes.retainAll(otherTypesOfInterest);

          /// Remove types that are known to be false on other paths; these
          /// would amount to knowing that a variable is or is not of some
          /// type.
          newTrueTypes.removeAll(otherFalseTypes);
          if (newTrueTypes.isEmpty) {
            newTrueTypes = null;
          } else {
            newTypesOfInterest.addAll(newTrueTypes);
          }
        }
        Set<ir.DartType> newFalseTypes;
        if (typeHolder.falseTypes != null) {
          newFalseTypes = new Set<ir.DartType>.from(typeHolder.falseTypes);

          /// Only types in [otherTypesOfInterest] has information from all
          /// paths.
          newFalseTypes.retainAll(otherTypesOfInterest);

          /// Remove types that are known to be true on other paths; these
          /// would amount to knowing that a variable is or is not of some
          /// type.
          newFalseTypes.removeAll(otherTrueTypes);
          if (newFalseTypes.isEmpty) {
            newFalseTypes = null;
          } else {
            newTypesOfInterest.addAll(newFalseTypes);
          }
        }
        if (newTrueTypes != null || newFalseTypes != null) {
          // Only include type holders with information.
          newTypeHolders
              .add(new TypeHolder(declaredType, newTrueTypes, newFalseTypes));
        }
      }
    }

    Set<ir.DartType> thisTrueTypes = new Set<ir.DartType>();
    Set<ir.DartType> thisFalseTypes = new Set<ir.DartType>();
    for (TypeHolder typeHolder in typeHolders) {
      if (typeHolder.trueTypes != null) {
        thisTrueTypes.addAll(typeHolder.trueTypes);
      }
      if (typeHolder.falseTypes != null) {
        thisFalseTypes.addAll(typeHolder.falseTypes);
      }
    }

    Set<ir.DartType> otherTrueTypes = new Set<ir.DartType>();
    Set<ir.DartType> otherFalseTypes = new Set<ir.DartType>();
    for (TypeHolder typeHolder in other.typeHolders) {
      if (typeHolder.trueTypes != null) {
        otherTrueTypes.addAll(typeHolder.trueTypes);
      }
      if (typeHolder.falseTypes != null) {
        otherFalseTypes.addAll(typeHolder.falseTypes);
      }
    }

    addTypeHolders(this.typeHolders, otherTrueTypes, otherFalseTypes,
        other.typesOfInterest);
    addTypeHolders(
        other.typeHolders, thisTrueTypes, thisFalseTypes, this.typesOfInterest);

    if (newTypeHolders.isEmpty) {
      assert(newTypesOfInterest.isEmpty);
      return null;
    }

    return new TargetInfo(declaredType, newTypeHolders, newTypesOfInterest);
  }

  /// Computes a single type that soundly represents the promoted type of the
  /// local variable on all possible paths.
  ir.DartType typeOf(ir.TypeEnvironment typeEnvironment) {
    ir.DartType candidate = null;
    for (TypeHolder typeHolder in typeHolders) {
      ir.DartType type = typeHolder.typeOf(typeEnvironment);
      if (type == null) {
        // We cannot promote. No single type is most specific.
        return null;
      }
      if (candidate == null) {
        candidate = type;
      } else {
        if (type == typeEnvironment.nullType) {
          // Keep the current candidate.
        } else if (candidate == typeEnvironment.nullType) {
          candidate = type;
        } else if (typeEnvironment.isSubtypeOf(
            candidate, type, ir.SubtypeCheckMode.ignoringNullabilities)) {
          candidate = type;
        } else if (!typeEnvironment.isSubtypeOf(
            type, candidate, ir.SubtypeCheckMode.ignoringNullabilities)) {
          // We cannot promote. No promoted type of one path is a supertype of
          // the promoted type from all other paths.
          // TODO(johnniwinther): Compute a greatest lower bound, instead?
          return null;
        }
      }
    }
    return candidate;
  }

  void _getText(
      StringBuffer sb, String Function(Iterable<ir.DartType>) typesToText) {
    sb.write('[');
    String comma = '';
    for (TypeHolder typeHolder in typeHolders) {
      sb.write(comma);
      typeHolder._getText(sb, typesToText);
      comma = ',';
    }
    sb.write('|');
    sb.write(typesToText(typesOfInterest));
    sb.write(']');
  }

  @override
  String toString() {
    StringBuffer sb = new StringBuffer();
    sb.write('TargetInfo(');
    sb.write('declaredType=$declaredType,');
    sb.write('typeHolders=$typeHolders,');
    sb.write('declarationsOfInterest=$typesOfInterest');
    sb.write(')');
    return sb.toString();
  }
}

/// Map from local variables to type information used for guarded type
/// promotion.
///
/// The terminology and implementation is based on this paper:
///
///   http://www.cs.williams.edu/FTfJP2011/6-Winther.pdf
///
class TypeMap {
  final Map<ir.VariableDeclaration, TargetInfo> _targetInfoMap;

  const TypeMap([this._targetInfoMap = const {}]);

  /// Returns the [TypeMap] that describes the added type knowledge for the
  /// local [variable]. If [isTrue] is `true`, the local [variable] is known to
  /// be an instance of [type]. If [isTrue] is `false`, the local [variable] is
  /// known _not_ to be an instance of [type].
  TypeMap promote(ir.VariableDeclaration variable, ir.DartType type,
      {bool isTrue}) {
    Map<ir.VariableDeclaration, TargetInfo> newInfoMap =
        new Map<ir.VariableDeclaration, TargetInfo>.from(_targetInfoMap);
    TargetInfo targetInfo = newInfoMap[variable];
    bool changed = false;
    if (targetInfo != null) {
      TargetInfo result = targetInfo.promote(type, isTrue: isTrue);
      changed = !identical(targetInfo, result);
      targetInfo = result;
    } else {
      changed = true;
      Set<ir.DartType> trueTypes =
          isTrue ? (new Set<ir.DartType>()..add(type)) : null;
      Set<ir.DartType> falseTypes =
          isTrue ? null : (new Set<ir.DartType>()..add(type));
      TypeHolder typeHolder =
          new TypeHolder(variable.type, trueTypes, falseTypes);
      targetInfo = new TargetInfo(
          variable.type, <TypeHolder>[typeHolder], <ir.DartType>[type]);
    }
    newInfoMap[variable] = targetInfo;
    return changed ? new TypeMap(newInfoMap) : this;
  }

  /// Returns the [TypeMap] that describes that the locals are either of [this]
  /// or the [other] types.
  TypeMap join(TypeMap other) {
    if (identical(this, other)) return this;

    Map<ir.VariableDeclaration, TargetInfo> newInfoMap = {};
    bool changed = false;
    _targetInfoMap.forEach((ir.VariableDeclaration variable, TargetInfo info) {
      TargetInfo result = info.join(other._targetInfoMap[variable]);
      changed |= !identical(info, result);
      if (result != null) {
        // Add only non-empty information.
        newInfoMap[variable] = result;
      }
    });
    return changed ? new TypeMap(newInfoMap) : this;
  }

  /// Returns the [TypeMap] in which all type information for any of the
  /// [variables] has been removed.
  TypeMap remove(Iterable<ir.VariableDeclaration> variables) {
    bool changed = false;
    Map<ir.VariableDeclaration, TargetInfo> newInfoMap = {};
    _targetInfoMap.forEach((ir.VariableDeclaration variable, TargetInfo info) {
      if (!variables.contains(variable)) {
        newInfoMap[variable] = info;
      } else {
        changed = true;
      }
    });
    return changed ? new TypeMap(newInfoMap) : this;
  }

  /// Returns the [TypeMap] where type information for `node.variable` is
  /// reduced to the promotions upheld by an assignment to `node.variable` of
  /// the static [type].
  TypeMap reduce(ir.VariableSet node, ir.DartType type,
      ir.TypeEnvironment typeEnvironment) {
    Map<ir.VariableDeclaration, TargetInfo> newInfoMap = {};
    bool changed = false;
    _targetInfoMap.forEach((ir.VariableDeclaration variable, TargetInfo info) {
      if (variable != node.variable) {
        newInfoMap[variable] = info;
      } else if (type != null) {
        changed = true;
        Set<ir.DartType> newTypesOfInterest = new Set<ir.DartType>();
        for (ir.DartType typeOfInterest in info.typesOfInterest) {
          if (typeEnvironment.isSubtypeOf(type, typeOfInterest,
              ir.SubtypeCheckMode.ignoringNullabilities)) {
            newTypesOfInterest.add(typeOfInterest);
          }
        }
        if (newTypesOfInterest.length > 1 ||
            (newTypesOfInterest.length == 1 &&
                newTypesOfInterest.single != info.declaredType)) {
          // If [newTypesOfInterest] only contains the declared type we have no
          // information about the variable (it is either an instance of its
          // declared type or null) and the canonical way to represent this is
          // to have _no_ target info.
          TypeHolder typeHolderIfNonNull =
              new TypeHolder(info.declaredType, newTypesOfInterest, null);
          TypeHolder typeHolderIfNull = new TypeHolder(info.declaredType, null,
              new Set<ir.DartType>()..add(info.declaredType));
          newInfoMap[variable] = new TargetInfo(
              info.declaredType,
              <TypeHolder>[typeHolderIfNonNull, typeHolderIfNull],
              newTypesOfInterest);
        }
      } else {
        changed = true;
      }
    });
    return changed ? new TypeMap(newInfoMap) : this;
  }

  /// Computes a single type that soundly represents the promoted type of
  /// `node.variable` on all possible paths.
  ir.DartType typeOf(ir.VariableGet node, ir.TypeEnvironment typeEnvironment) {
    TargetInfo info = _targetInfoMap[node.variable];
    ir.DartType type;
    if (info != null) {
      type = info.typeOf(typeEnvironment);
    }
    return type ?? node.promotedType ?? node.variable.type;
  }

  String getText(String Function(Iterable<ir.DartType>) typesToText) {
    StringBuffer sb = new StringBuffer();
    sb.write('{');
    String comma = '';
    _targetInfoMap.forEach((ir.VariableDeclaration variable, TargetInfo info) {
      sb.write('${comma}${variable.name}:');
      info._getText(sb, typesToText);
      comma = ',';
    });
    sb.write('}');
    return sb.toString();
  }

  @override
  String toString() {
    StringBuffer sb = new StringBuffer();
    sb.write('TypeMap(');
    String comma = '';
    _targetInfoMap.forEach((ir.VariableDeclaration variable, TargetInfo info) {
      sb.write('${comma}$variable->$info');
      comma = ',';
    });
    sb.write(')');
    return sb.toString();
  }
}
