// 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/type_environment.dart' as ir;
// ignore: implementation_imports
import 'package:front_end/src/api_prototype/static_weak_references.dart'
    as ir
    show StaticWeakReferences;

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/util.dart';
import '../js_backend/field_analysis.dart';
import '../js_model/element_map.dart';
import '../js_model/elements.dart';
import '../js_model/locals.dart' show JumpVisitor;
import '../js_model/js_world.dart';
import '../native/behavior.dart';
import '../options.dart';
import '../universe/member_hierarchy.dart';
import '../universe/record_shape.dart';
import '../universe/selector.dart';
import '../universe/side_effects.dart';
import '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.VisitorDefault<TypeInformation?>
    with ir.VisitorNullMixin<TypeInformation> {
  final CompilerOptions _options;
  final JClosedWorld _closedWorld;
  final InferrerEngine _inferrer;
  final TypeSystem _types;
  final MemberEntity _analyzedMember;
  final ir.Node? _analyzedNode;
  final KernelToLocalsMap _localsMap;
  final GlobalTypeInferenceElementData _memberData;
  final MemberHierarchyBuilder _memberHierarchyBuilder;
  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.
  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;
  }

  /// Removes from the current [_state] any data from the boolean value of the
  /// most recently visited node.
  void _clearConditionalStateAfter() {
    _stateAfterWhenTrueInternal = _stateAfterWhenFalseInternal = null;
  }

  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 = <Local>{};
  final Map<Local, FieldEntity> _capturedAndBoxed;

  /// 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._staticTypeContext,
    this._memberHierarchyBuilder, [
    LocalState? previousState,
    Map<Local, FieldEntity>? capturedAndBoxed,
  ]) : _types = _inferrer.types,
       _memberData = _inferrer.dataOfMember(_analyzedMember),
       // TODO(johnniwinther): Should side effects also be tracked for field
       // initializers?
       _sideEffectsBuilder = _analyzedMember is FunctionEntity
           ? _inferrer.inferredDataBuilder.getSideEffectsBuilder(
               _analyzedMember,
             )
           : SideEffectsBuilder.free(_analyzedMember),
       _inGenerativeConstructor = _analyzedNode is ir.Constructor,
       _capturedAndBoxed = capturedAndBoxed != null
           ? Map<Local, FieldEntity>.from(capturedAndBoxed)
           : <Local, FieldEntity>{},
       _stateInternal =
           previousState ??
           LocalState.initial(
             inGenerativeConstructor: _analyzedNode is ir.Constructor,
           );

  JsToElementMap get _elementMap => _closedWorld.elementMap;

  ClosureData get _closureDataLookup => _closedWorld.closureDataLookup;

  // Null for members without an associated Kernel node. No static types should
  // be queried for these members.
  final ir.StaticTypeContext? _staticTypeContext;

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

  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) {
    final 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 is FieldEntity) {
          final 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 is FieldEntity) {
      if (_analyzedNode == null ||
          isNullLiteral(_analyzedNode as ir.Expression)) {
        // 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].
    if (!_analyzedMember.isAbstract) {
      ScopeInfo scopeInfo = _closureDataLookup.getScopeInfo(_analyzedMember);
      scopeInfo.forEachBoxedVariable(_localsMap, (variable, field) {
        _capturedAndBoxed[variable] = field;
      });
    }

    return visit(_analyzedNode)!;
  }

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

  late final TypeInformation thisType = () {
    final cls = _elementMap.getMemberThisType(_analyzedMember)!.element;
    if (_closedWorld.isUsedAsMixin(cls)) {
      return _types.nonNullSubtype(cls);
    } else {
      return _types.nonNullSubclass(cls);
    }
  }();

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

    // Clear the conditional state to ensure we don't accidentally carry over
    // conclusions from a nested condition into an outer condition. For example:
    //
    //   if (methodCall(x is T && true)) { /* don't assume x is T here. */ }
    if (!conditionContext) _clearConditionalStateAfter();
    _accumulateIsChecks = oldAccumulateIsChecks;
    return result;
  }

  void handleParameter(
    ir.VariableDeclaration node, {
    required bool isOptional,
  }) {
    Local local = _localsMap.getLocalVariable(node);
    final parameterType = _inferrer.typeOfParameter(local);
    _state.setLocal(_inferrer, _capturedAndBoxed, local, parameterType);

    if (isOptional) {
      TypeInformation type;
      if (node.initializer != null) {
        type = visit(node.initializer)!;
        if (_inferrer.abstractValueDomain.isNull(type.type).isDefinitelyTrue &&
            !node.type.isPotentiallyNullable) {
          // TODO(52582): Make optional nonnullable parameters nullable until
          // such a case from redirecting factories is a compile-time error.
          //
          // In rare cases (e.g. optional parameters on redirecting factories)
          // the CFE can give us a non-nullable parameter with a null
          // initializer. Ideally we would take the type of the initializer on
          // the target parameter but instead we're conservative and treat the
          // parameter as nullable.
          parameterType.isOptionalNoDefault = true;
        }
      } else {
        type = _types.nullType;
      }
      _inferrer.setDefaultTypeOfParameter(local, type);
    }
  }

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

    final 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 is FieldEntity &&
            member.isInstanceMember &&
            member.isAssignable) {
          final type = _state.readField(member);
          MemberDefinition definition = _elementMap.getMemberDefinition(member);
          assert(definition.kind == MemberKind.regular);
          final node = definition.node as ir.Field;
          final initializer = node.initializer;
          if (type == null &&
              (initializer == null || isNullLiteral(initializer))) {
            _inferrer.recordTypeOfField(member, _types.nullType);
          }
        }
      });
    }
    _inferrer.recordExposesThis(
      _analyzedMember as ConstructorEntity,
      _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
  Null visitFieldInitializer(ir.FieldInitializer node) {
    final rhsType = visit(node.value)!;
    FieldEntity field = _elementMap.getField(node.field);
    _state.updateField(field, rhsType);
    _inferrer.recordTypeOfField(field, rhsType);
    return null;
  }

  @override
  Null 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
  Null 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
  Null 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 as FunctionEntity);
      _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;
    }
    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
  Never defaultStatement(ir.Statement node) {
    throw UnimplementedError(
      'Unhandled statement: $node (${node.runtimeType})',
    );
  }

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

  TypeInformation createNullTypeInformation() {
    return _types.nullType;
  }

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

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

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

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

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

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

  @override
  Null 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
  Null visitLabeledStatement(ir.LabeledStatement node) {
    ir.Statement body = node.body;
    if (JumpVisitor.canBeBreakTarget(body)) {
      // Loops and switches handle their own labels.
      visit(body);
    } else {
      final stateBefore = _state;
      final 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
  Null visitSwitchStatement(ir.SwitchStatement node) {
    visit(node.expression);

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

    List<JumpTarget> continueTargets = <JumpTarget>[];
    bool hasDefaultCase = false;
    for (ir.SwitchCase switchCase in node.cases) {
      final continueTarget = _localsMap.getJumpTargetForSwitchCase(switchCase);
      if (continueTarget != null) {
        continueTargets.add(continueTarget);
      }
      if (switchCase.isDefault) {
        hasDefaultCase = true;
      }
    }
    final stateBefore = _state;
    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;
      stateBefore.startLoop(_inferrer, node);
      do {
        changed = false;
        // We first visit every case and collect the updated continue states.
        // We must do a full pass as the jumps may be to earlier cases.
        _visitCasesForSwitch(node, stateBefore);

        // We then pass back over the cases and update the state of any continue
        // targets with the states we collected in the last pass.
        for (ir.SwitchCase switchCase in node.cases) {
          final continueTarget = _localsMap.getJumpTargetForSwitchCase(
            switchCase,
          );
          if (continueTarget != null) {
            changed |= stateBefore.mergeAll(
              _inferrer,
              _getLoopBackEdges(continueTarget),
            );
          }
        }
      } while (changed);
      stateBefore.endLoop(_inferrer, node);

      continueTargets.forEach(_clearBreaksAndContinues);
    } else {
      // Gather the termination states of each case by visiting all the breaks.
      _visitCasesForSwitch(node, stateBefore);
    }

    // Combine all the termination states accumulated from all the visited
    // breaks that target this switch.
    _state = stateBefore.mergeAfterBreaks(
      _inferrer,
      _getBreaks(jumpTarget),
      keepOwnLocals: !hasDefaultCase,
    );
    _clearBreaksAndContinues(jumpTarget);
    return null;
  }

  void _visitCasesForSwitch(ir.SwitchStatement node, LocalState stateBefore) {
    for (ir.SwitchCase switchCase in node.cases) {
      _state = LocalState.childPath(stateBefore);
      visit(switchCase);
    }
  }

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

  @override
  Null 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, {
    required 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, () {
      PhiElementTypeInformation? 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++;
      }
      final simplifiedElementType = elementType == null
          ? _types.nonNullEmpty()
          : _types.simplifyPhi(null, null, elementType);
      TypeInformation containerType = isConst
          ? _types.constListType
          : _types.growableListType;
      return _types.allocateList(
        containerType,
        node,
        _analyzedMember,
        simplifiedElementType,
        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, {
    required bool isConst,
  }) {
    return _inferrer.concreteTypes.putIfAbsent(node, () {
      PhiElementTypeInformation? elementType;
      for (TypeInformation type in elementTypes) {
        elementType = elementType == null
            ? _types.allocatePhi(null, null, type, isTry: false)
            : _types.addPhiInput(null, elementType, type);
      }
      final simplifiedElementType = elementType == null
          ? _types.nonNullEmpty()
          : _types.simplifyPhi(null, null, elementType);
      TypeInformation containerType = isConst
          ? _types.constSetType
          : _types.setType;
      return _types.allocateSet(
        containerType,
        node,
        _analyzedMember,
        simplifiedElementType,
      );
    });
  }

  @override
  TypeInformation visitMapLiteral(ir.MapLiteral node) {
    return createMapTypeInformation(
      node,
      node.entries.map((e) => (visit(e.key)!, visit(e.value)!)),
      isConst: node.isConst,
      keyStaticType: _elementMap.getDartType(node.keyType),
      valueStaticType: _elementMap.getDartType(node.valueType),
    );
  }

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

      for ((TypeInformation, TypeInformation) entryType in entryTypes) {
        keyTypes.add(entryType.$1);
        valueTypes.add(entryType.$2);
      }

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

  @override
  TypeInformation visitRecordLiteral(ir.RecordLiteral node) {
    final recordType = _elementMap.getDartType(node.recordType) as RecordType;
    final fieldValues = [
      for (final expression in node.positional) visit(expression)!,
      for (final namedExpression in node.named) visit(namedExpression.value)!,
    ];
    return createRecordTypeInformation(
      node,
      recordType,
      fieldValues,
      isConst: node.isConst,
    );
  }

  TypeInformation createRecordTypeInformation(
    ir.TreeNode node,
    RecordType recordType,
    List<TypeInformation> fieldTypes, {
    required bool isConst,
  }) {
    return _types.allocateRecord(node, recordType, fieldTypes, isConst);
  }

  @override
  TypeInformation? visitReturnStatement(ir.ReturnStatement node) {
    final 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,
        type,
      );
    } else {
      _state.updateLocal(
        _inferrer,
        _capturedAndBoxed,
        local,
        visit(node.initializer)!,
        type,
      );
    }
    if (node.initializer is ir.ThisExpression) {
      _state.markThisAsExposed();
    }
    return null;
  }

  @override
  TypeInformation? visitVariableGet(ir.VariableGet node) {
    Local local = _localsMap.getLocalVariable(node.variable);
    return _state.readLocal(_inferrer, _capturedAndBoxed, local);
  }

  @override
  TypeInformation visitVariableSet(ir.VariableSet node) {
    final 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, 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.Expression receiver) {
    final data = _memberData as KernelGlobalTypeInferenceElementData;
    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 = 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,
    );
    final callMethod = info.callMethod!;
    TypeInformation type = handleStaticInvoke(
      node,
      selector,
      callMethod,
      argumentsTypes,
    );
    FunctionType functionType = _elementMap.elementEnvironment.getFunctionType(
      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 as ir.FunctionDeclaration,
      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.expression);
    return _types.boolType;
  }

  TypeInformation _handleMethodInvocation(
    ir.Expression node,
    ir.Expression receiver,
    TypeInformation receiverType,
    Selector selector,
    ArgumentsTypes arguments,
    ir.Member? interfaceTarget,
  ) {
    final 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(right);
    }
    if (rightIsNull) {
      // [left] is `null` if [node] evaluates to `true`.
      _potentiallyAddNullCheck(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) {
    final leftType = visit(node.left)!;
    final 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;
    final 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;
    final 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;
    final 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;
    final 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.TreeNode node,
    Selector selector,
    AbstractValue? mask,
    TypeInformation receiverType,
    ArgumentsTypes? arguments,
    ir.VariableDeclaration? variable,
  ) {
    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,
          type,
          excludeNull: !selector.appliesToNullWithoutThrow(),
        );
      }
    }

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

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

  TypeInformation handleDynamicSet(
    ir.TreeNode 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.TreeNode 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) {
      final 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 {
      final expressionType = visit(node.iterable)!;
      Selector iteratorSelector = Selectors.iterator;
      final 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,
      variableType,
    );

    final 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) {
    if (element == null) return;
    _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]!);
  }

  Null handleLoop(ir.Node node, JumpTarget? target, void Function() logic) {
    _loopLevel++;
    bool changed = false;
    final 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) {
      final constant = firstArgument.constant as ir.DoubleConstant;
      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 is JField) {
        FieldAnalysisData fieldData = _closedWorld.fieldAnalysis.getFieldData(
          member,
        );
        final constantValue = fieldData.constantValue;
        if (fieldData.isEffectivelyConstant &&
            constantValue is IntConstantValue) {
          BigInt intValue = constantValue.intValue;
          if (intValue.isValidInt) {
            return finish(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, {
    required 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.dartNativeTypedData &&
        _closedWorld.nativeData.isNativeClass(cls) &&
        _closedWorld.classHierarchy.isSubtypeOf(
          cls,
          _closedWorld.commonElements.typedDataClass,
        ) &&
        _closedWorld.classHierarchy.isSubtypeOf(
          cls,
          _closedWorld.commonElements.listClass,
        ) &&
        constructor.name == '';
  }

  TypeInformation handleConstructorInvoke(
    ir.TreeNode 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.isNamedListConstructor('filled', constructor)) {
      // We have something like `List.filled(len, fill)`.
      final 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)`.
      final 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)) {
      final 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,
    )) {
      final 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,
    )) {
      final 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)`.
      final length = _findLength(arguments);
      final member = _elementMap.elementEnvironment.lookupClassMember(
        constructor.enclosingClass,
        Names.indexName,
      )!;
      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 handleForeignInvoke(
    ir.StaticInvocation node,
    FunctionEntity function,
    ArgumentsTypes arguments,
    Selector selector,
  ) {
    final 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.jsEmbeddedGlobal) {
      NativeBehavior nativeBehavior = _elementMap
          .getNativeBehaviorForJsEmbeddedGlobalCall(node);
      _sideEffectsBuilder.add(nativeBehavior.sideEffects);
      return _inferrer.typeOfNativeBehavior(nativeBehavior);
    } else if (name == Identifiers.jsBuiltin) {
      NativeBehavior nativeBehavior = _elementMap
          .getNativeBehaviorForJsBuiltinCall(node);
      _sideEffectsBuilder.add(nativeBehavior.sideEffects);
      return _inferrer.typeOfNativeBehavior(nativeBehavior);
    } else if (name == Identifiers.jsStringConcat) {
      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) {
    if (ir.StaticWeakReferences.isWeakReference(node)) {
      final weakTarget = ir.StaticWeakReferences.getWeakReferenceTarget(node);
      if (_elementMap.containsMethod(weakTarget)) {
        return visit(ir.StaticWeakReferences.getWeakReferenceArgument(node))!;
      }
      return _types.nullType;
    }
    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 as FunctionEntity,
        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 (_closedWorld.commonElements.isIsSentinel(member)) {
      handleStaticInvoke(node, selector, member, arguments);

      // Calls to `isSentinel` can only come from the late lowering kernel
      // transformation.
      final value = node.arguments.positional.single as ir.VariableGet;

      Local local = _localsMap.getLocalVariable(value.variable);
      DartType localType = _localsMap.getLocalType(_elementMap, local);
      LocalState stateWhenSentinel = LocalState.childPath(_state);
      LocalState stateWhenNotSentinel = LocalState.childPath(_state);

      // Narrow tested variable to late sentinel on true branch.
      stateWhenSentinel.updateLocal(
        _inferrer,
        _capturedAndBoxed,
        local,
        _types.lateSentinelType,
        localType,
      );

      // Narrow tested variable to not late sentinel on false branch.
      final currentTypeInformation = stateWhenNotSentinel.readLocal(
        _inferrer,
        _capturedAndBoxed,
        local,
      )!;
      stateWhenNotSentinel.updateLocal(
        _inferrer,
        _capturedAndBoxed,
        local,
        currentTypeInformation,
        localType,
        excludeLateSentinel: true,
      );

      _setStateAfter(_state, stateWhenSentinel, stateWhenNotSentinel);

      return _types.boolType;
    } else if (member is ConstructorEntity) {
      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 as FunctionEntity);
      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) {
    return _types.asyncFutureType;
  }

  @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) {
    final 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,
  }) {
    final receiverType = visit(receiver)!;
    Selector selector = _elementMap.getSelector(node);
    final 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);
  }

  TypeInformation _handleRecordFieldGet(
    ir.Expression node,
    ir.Expression receiver,
    String fieldName,
  ) {
    final receiverType = visit(receiver)!;
    _typeOfReceiver(node, receiver);
    return _types.allocateRecordFieldGet(
      node,
      fieldName,
      receiverType,
      _analyzedMember,
    );
  }

  @override
  TypeInformation visitRecordIndexGet(ir.RecordIndexGet node) {
    return _handleRecordFieldGet(
      node,
      node.receiver,
      RecordShape.positionalFieldIndexToGetterName(node.index),
    );
  }

  @override
  TypeInformation visitRecordNameGet(ir.RecordNameGet node) {
    return _handleRecordFieldGet(node, node.receiver, node.name);
  }

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

  TypeInformation _handlePropertySet(
    ir.Expression node,
    ir.Expression receiver,
    ir.Expression value,
  ) {
    final receiverType = visit(receiver)!;
    Selector selector = _elementMap.getSelector(node);
    final mask = _typeOfReceiver(node, receiver);

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

    if (_inGenerativeConstructor && receiver is ir.ThisExpression) {
      final typedMask = _types.newTypedSelector(receiverType, mask);
      if (!_closedWorld.includesClosureCall(selector, typedMask)) {
        Iterable<DynamicCallTarget> targets = _memberHierarchyBuilder
            .rootsForCall(typedMask, selector);
        // We just recognized a field initialization of the form:
        // `this.foo = 42`. If there is only one non-virtual target, we can
        // update its type. If the target is virtual then technically overrides
        // of the target are also valid targets and we cannot make this update.
        if (targets.length == 1 && !targets.single.isVirtual) {
          MemberEntity single = targets.single.member;
          if (single is FieldEntity) {
            final 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);
  }

  @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) {
    return visit(node, conditionContext: true);
  }

  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.
      final currentTypeInformation = stateAfterCheckWhenTrue.readLocal(
        _inferrer,
        _capturedAndBoxed,
        local,
      )!;
      stateAfterCheckWhenTrue.updateLocal(
        _inferrer,
        _capturedAndBoxed,
        local,
        currentTypeInformation,
        localType,
        isCast: false,
      );
      _setStateAfter(_state, stateAfterCheckWhenTrue, stateAfterCheckWhenFalse);
    }
  }

  void _potentiallyAddNullCheck(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,
        localType,
      );

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

  @override
  TypeInformation? visitIfStatement(ir.IfStatement node) {
    final stateBefore = _state;
    handleCondition(node.condition);
    final stateAfterConditionWhenTrue = _stateAfterWhenTrue;
    final stateAfterConditionWhenFalse = _stateAfterWhenFalse;
    _state = LocalState.childPath(stateAfterConditionWhenTrue);
    visit(node.then);
    final stateAfterThen = _state;
    _state = LocalState.childPath(stateAfterConditionWhenFalse);
    visit(node.otherwise);
    final 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);
    final stateAfterOperandWhenTrue = _stateAfterWhenTrue;
    final 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) {
      final stateBefore = _state;
      _state = LocalState.childPath(stateBefore);
      final leftInfo = handleCondition(node.left)!;
      final stateAfterLeftWhenTrue = _stateAfterWhenTrue;
      final stateAfterLeftWhenFalse = _stateAfterWhenFalse;
      _state = LocalState.childPath(stateAfterLeftWhenTrue);
      final rightInfo = handleCondition(node.right)!;
      final stateAfterRightWhenTrue = _stateAfterWhenTrue;
      final stateAfterRightWhenFalse = _stateAfterWhenFalse;
      final 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) {
      final stateBefore = _state;
      _state = LocalState.childPath(stateBefore);
      final leftInfo = handleCondition(node.left)!;
      final stateAfterLeftWhenTrue = _stateAfterWhenTrue;
      final stateAfterLeftWhenFalse = _stateAfterWhenFalse;
      _state = LocalState.childPath(stateAfterLeftWhenFalse);
      final rightInfo = handleCondition(node.right)!;
      final stateAfterRightWhenTrue = _stateAfterWhenTrue;
      final 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(
      currentElementSpannable,
      "Unexpected logical operator '${node.operatorEnum}'.",
    );
  }

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

  TypeInformation handleLocalFunction(
    ir.LocalFunction 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);
    final callMethod = info.callMethod!;

    // 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);
        }
        final 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(callMethod);
      },
    );
    if (variable != null) {
      Local local = _localsMap.getLocalVariable(variable);
      DartType type = _localsMap.getLocalType(_elementMap, local);
      _state.updateLocal(
        _inferrer,
        _capturedAndBoxed,
        local,
        localFunctionType,
        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,
      callMethod,
      functionNode,
      _localsMap,
      _staticTypeContext,
      _memberHierarchyBuilder,
      closureState,
      _capturedAndBoxed,
    );
    visitor.run();
    _inferrer.recordReturnType(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
  Null visitWhileStatement(ir.WhileStatement node) {
    return handleLoop(node, _localsMap.getJumpTargetForWhile(node), () {
      handleCondition(node.condition);
      _state = LocalState.childPath(_stateAfterWhenTrue);
      visit(node.body);
    });
  }

  @override
  Null 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 = LocalState.childPath(_stateAfterWhenTrue, node.body);
    });
  }

  @override
  Null 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
  Null visitTryCatch(ir.TryCatch node) {
    final stateBefore = _state;
    _state = LocalState.tryBlock(stateBefore, node);
    _state.markInitializationAsIndefinite();
    visit(node.body);
    final stateAfterTry = _state;
    // If the try block contains a throw, then `stateAfterBody.aborts` will be
    // true. The catch needs to be aware of the results of inference from the
    // try block since we may get there via the abortive control flow:
    //
    // dynamic x = "bad";
    // try {
    //   ...
    //   x = 0;
    //   throw ...;
    // } catch (_) {
    //   print(x + 42); <-- x may be 0 here.
    // }
    //
    // Note that this will also cause us to ignore aborts due to breaks,
    // returns, and continues. Since these control flow constructs will not jump
    // to a catch block, this may cause some types flowing into the catch block
    // to be wider than necessary:
    //
    // dynamic x = "bad";
    // try {
    //   x = 0;
    //   return;
    // } catch (_) {
    //   print(x + 42); <-- x cannot be 0 here.
    // }
    _state = stateBefore.mergeTry(_inferrer, stateAfterTry);
    for (ir.Catch catchBlock in node.catches) {
      final stateBeforeCatch = _state;
      _state = LocalState.childPath(stateBeforeCatch);
      visit(catchBlock);
      final stateAfterCatch = _state;
      _state = stateBeforeCatch.mergeCatch(_inferrer, stateAfterCatch);
    }

    return null;
  }

  @override
  Null visitTryFinally(ir.TryFinally node) {
    final stateBefore = _state;
    _state = LocalState.tryBlock(stateBefore, node);
    _state.markInitializationAsIndefinite();
    visit(node.body);
    // Even if the try block contains abortive control flow, the finally block
    // needs to be aware of the results of inference from the try block since we
    // still reach the finally after abortive control flow:
    //
    // dynamic x = "bad";
    // try {
    //   ...
    //   x = 0;
    //   return;
    // } finally {
    //   print(x + 42); <-- x may be 0 here.
    // }
    _state = stateBefore.mergeTry(_inferrer, _state);
    final stateBeforeFinalizer = _state;
    // Use a child path to reset abort state before continuing into the
    // `finally` block.
    _state = LocalState.childPath(stateBeforeFinalizer);
    visit(node.finalizer);
    // Continue with a copy of the state after the finalizer since control flow
    // should continue linearly. Update abort state to account for try/catch
    // aborting.
    _state = LocalState.childPath(_state)
      ..seenReturnOrThrow =
          _state.seenReturnOrThrow || stateBeforeFinalizer.seenReturnOrThrow
      ..seenBreakOrContinue =
          _state.seenBreakOrContinue ||
          stateBeforeFinalizer.seenBreakOrContinue;
    return null;
  }

  @override
  Null visitCatch(ir.Catch node) {
    final exception = node.exception;
    if (exception != null) {
      TypeInformation mask;
      DartType type = _elementMap.getDartType(node.guard).withoutNullability;
      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,
        _dartTypes.dynamicType(),
        excludeNull: true /* `throw null` produces a TypeError */,
      );
    }
    final 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,
        _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();
  }

  @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();

    final target = getEffectiveSuperTarget(node.interfaceTarget);
    Selector selector = Selector.getter(_elementMap.getName(node.name));
    MemberEntity member = _elementMap.getMember(target);
    TypeInformation type = handleStaticInvoke(node, selector, member, null);
    if (member.isGetter) {
      FunctionType functionType = _elementMap.elementEnvironment
          .getFunctionType(member as FunctionEntity);
      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 is FieldEntity) {
      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();

    final rhsType = visit(node.value)!;
    final target = getEffectiveSuperTarget(node.interfaceTarget);
    Selector selector = Selector.setter(_elementMap.getName(node.name));
    ArgumentsTypes arguments = ArgumentsTypes([rhsType], null);
    final member = _elementMap.getMember(target);
    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();

    final target = getEffectiveSuperTarget(node.interfaceTarget);
    ArgumentsTypes arguments = analyzeArguments(node.arguments);
    Selector selector = _elementMap.getSelector(node);
    MemberEntity member = _elementMap.getMember(target);
    assert(member.isFunction, "Unexpected super invocation target: $member");
    member as FunctionEntity;
    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) {
    final operandType = visit(node.operand)!;
    return _types.narrowType(operandType, _elementMap.getDartType(node.type));
  }

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

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

  @override
  TypeInformation visitYieldStatement(ir.YieldStatement node) {
    final 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);
  }

  @override
  TypeInformation visitFileUriExpression(ir.FileUriExpression node) {
    return visit(node.expression)!;
  }
}

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

  TypeInformationConstantVisitor(this.builder, this.expression);

  static Never _unexpectedConstant(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) => (visitConstant(e.key), visitConstant(e.value))),
      isConst: true,
      keyStaticType: builder._elementMap.getDartType(node.keyType),
      valueStaticType: builder._elementMap.getDartType(node.valueType),
    );
  }

  @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 visitRecordConstant(ir.RecordConstant node) {
    final recordType =
        builder._elementMap.getDartType(node.recordType) as RecordType;
    final fieldValues = [
      for (final value in node.positional) visitConstant(value),
      for (final value in node.named.values) visitConstant(value),
    ];
    return builder.createRecordTypeInformation(
      ConstantReference(expression, node),
      recordType,
      fieldValues,
      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;
  }

  @override
  Never visitConstructorTearOffConstant(ir.ConstructorTearOffConstant node) =>
      _unexpectedConstant(node);

  @override
  Never visitRedirectingFactoryTearOffConstant(
    ir.RedirectingFactoryTearOffConstant node,
  ) => _unexpectedConstant(node);

  @override
  Never visitTypedefTearOffConstant(ir.TypedefTearOffConstant node) =>
      _unexpectedConstant(node);

  @override
  Never visitAuxiliaryConstant(ir.AuxiliaryConstant node) =>
      _unexpectedConstant(node);
}

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({required 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);
    final 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, {
    required this.seenReturnOrThrow,
    required this.seenBreakOrContinue,
  });

  bool get aborts {
    return seenReturnOrThrow || seenBreakOrContinue;
  }

  bool get isThisExposed {
    return _fields?.isThisExposed ?? true;
  }

  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,
  ) {
    final field = capturedAndBoxed[local];
    if (field != null) {
      return inferrer.typeOfMember(field);
    } else {
      return _locals.use(local);
    }
  }

  void updateLocal(
    InferrerEngine inferrer,
    Map<Local, FieldEntity> capturedAndBoxed,
    Local local,
    TypeInformation type,
    DartType staticType, {
    bool isCast = true,
    bool excludeNull = false,
    bool excludeLateSentinel = false,
  }) {
    setLocal(
      inferrer,
      capturedAndBoxed,
      local,
      inferrer.types.narrowType(
        type,
        staticType,
        isCast: isCast,
        excludeNull: excludeNull,
        excludeLateSentinel: excludeLateSentinel,
      ),
    );
  }

  void setLocal(
    InferrerEngine inferrer,
    Map<Local, FieldEntity> capturedAndBoxed,
    Local local,
    TypeInformation type,
  ) {
    final field = capturedAndBoxed[local];
    if (field != null) {
      inferrer.recordTypeOfField(field, type);
    } else {
      _locals.update(inferrer, local, type, _tryBlock);
    }
  }

  LocalState mergeTry(InferrerEngine inferrer, LocalState other) {
    final locals = _locals.mergeFlow(inferrer, other._locals);
    return LocalState.internal(
      locals,
      _fields,
      _tryBlock,
      seenReturnOrThrow: seenReturnOrThrow || other.seenReturnOrThrow,
      seenBreakOrContinue: seenBreakOrContinue || other.seenBreakOrContinue,
    );
  }

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

  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,
      );
    }

    final 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 allBranchesReturnOrThrow = true;
    for (LocalState state in states) {
      allBranchesReturnOrThrow &= state.seenReturnOrThrow;
    }

    keepOwnLocals &= !seenReturnOrThrow;

    LocalsHandler locals = _locals.mergeAfterBreaks(
      inferrer,
      states
          .where((LocalState state) => !state.seenReturnOrThrow)
          .map((LocalState state) => state._locals),
      keepOwnLocals: keepOwnLocals,
    );
    seenReturnOrThrow = allBranchesReturnOrThrow && !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();
  }
}
