// Copyright (c) 2019, 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:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_system.dart' show TypeSystemImpl;
import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
import 'package:analyzer/src/error/best_practices_verifier.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:meta/meta.dart';
import 'package:nnbd_migration/fix_reason_target.dart';
import 'package:nnbd_migration/instrumentation.dart';
import 'package:nnbd_migration/nnbd_migration.dart';
import 'package:nnbd_migration/src/conditional_discard.dart';
import 'package:nnbd_migration/src/decorated_class_hierarchy.dart';
import 'package:nnbd_migration/src/decorated_type.dart';
import 'package:nnbd_migration/src/edge_origin.dart';
import 'package:nnbd_migration/src/expression_checks.dart';
import 'package:nnbd_migration/src/nullability_node.dart';
import 'package:nnbd_migration/src/nullability_node_target.dart';
import 'package:nnbd_migration/src/utilities/built_value_transformer.dart';
import 'package:nnbd_migration/src/utilities/completeness_tracker.dart';
import 'package:nnbd_migration/src/utilities/hint_utils.dart';
import 'package:nnbd_migration/src/utilities/permissive_mode.dart';
import 'package:nnbd_migration/src/utilities/resolution_utils.dart';
import 'package:nnbd_migration/src/utilities/scoped_set.dart';
import 'package:nnbd_migration/src/utilities/where_not_null_transformer.dart';
import 'package:nnbd_migration/src/utilities/where_or_null_transformer.dart';
import 'package:nnbd_migration/src/variables.dart';

import 'decorated_type_operations.dart';

/// A potentially reversible decision is that downcasts and sidecasts should
/// assume non-nullability. This could be changed such that we assume the
/// widest type, or the narrowest type. For now we assume non-nullability, but
/// have a flag to isolate that work.
const _assumeNonNullabilityInCasts = true;

/// Test class mixing in _AssignmentChecker, to allow [checkAssignment] to be
/// more easily unit tested.
@visibleForTesting
class AssignmentCheckerForTesting extends Object with _AssignmentChecker {
  @override
  final TypeSystem _typeSystem;

  @override
  final TypeProvider typeProvider;

  final NullabilityGraph _graph;

  /// Tests should fill in this map with the bounds of any type parameters being
  /// tested.
  final Map<TypeParameterElement, DecoratedType> bounds = {};

  @override
  final DecoratedClassHierarchy _decoratedClassHierarchy;

  AssignmentCheckerForTesting(this._typeSystem, this.typeProvider, this._graph,
      this._decoratedClassHierarchy);

  void checkAssignment(EdgeOrigin origin,
      {required DecoratedType source,
      required DecoratedType destination,
      required bool hard}) {
    super._checkAssignment(origin, FixReasonTarget.root,
        source: source, destination: destination, hard: hard);
  }

  @override
  void _connect(NullabilityNode? source, NullabilityNode? destination,
      EdgeOrigin origin, FixReasonTarget edgeTarget,
      {bool hard = false, bool checkable = true}) {
    _graph.connect(source, destination!, origin,
        hard: hard, checkable: checkable);
  }

  @override
  DecoratedType? _getCallMethodType(DecoratedType type) => null;

  @override
  DecoratedType _getTypeParameterTypeBound(DecoratedType type) {
    return bounds[(type.type as TypeParameterType).element] ??
        (throw StateError('Unknown bound for $type'));
  }
}

/// Visitor that builds nullability graph edges by examining code to be
/// migrated.
///
/// The return type of each `visit...` method is a [DecoratedType] indicating
/// the static type of the visited expression, along with the constraint
/// variables that will determine its nullability.  For `visit...` methods that
/// don't visit expressions, `null` will be returned.
class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
    with
        _AssignmentChecker,
        PermissiveModeVisitor<DecoratedType>,
        CompletenessTracker<DecoratedType>,
        ResolutionUtils {
  final TypeSystem _typeSystem;

  final InheritanceManager3 _inheritanceManager;

  /// The repository of constraint variables and decorated types (from a
  /// previous pass over the source code).
  final Variables? _variables;

  final NullabilityMigrationListener? listener;

  final NullabilityMigrationInstrumentation? instrumentation;

  final NullabilityGraph _graph;

  TypeProvider typeProvider;

  @override
  final Source? source;

  @override
  final DecoratedClassHierarchy? _decoratedClassHierarchy;

  /// If we are visiting a function body or initializer, instance of flow
  /// analysis.  Otherwise `null`.
  FlowAnalysis<AstNode, Statement, Expression, PromotableElement,
      DecoratedType>? _flowAnalysis;

  /// If we are visiting a function body or initializer, assigned variable
  /// information used in flow analysis.  Otherwise `null`.
  AssignedVariables<AstNode, PromotableElement>? _assignedVariables;

  /// The [DecoratedType] of the innermost function or method being visited, or
  /// `null` if the visitor is not inside any function or method.
  ///
  /// This is needed to construct the appropriate nullability constraints for
  /// return statements.
  DecoratedType? _currentFunctionType;

  /// If the innermost enclosing executable is a constructor with field formal
  /// parameters, a map from each field's getter to the corresponding field
  /// formal parameter element.  Otherwise, an empty map.
  Map<PropertyAccessorElement, FieldFormalParameterElement>
      _currentFieldFormals = const {};

  FunctionExpression? _currentFunctionExpression;

  /// The [ClassElement] or [ExtensionElement] of the current class or extension
  /// being visited, or null.
  Element? _currentClassOrExtension;

  /// If an extension declaration is being visited, the decorated type of the
  /// type appearing in the `on` clause (this is the type of `this` inside the
  /// extension declaration).  Null if an extension declaration is not being
  /// visited.
  DecoratedType? _currentExtendedType;

  /// The [DecoratedType] of the innermost list or set literal being visited, or
  /// `null` if the visitor is not inside any list or set.
  ///
  /// This is needed to construct the appropriate nullability constraints for
  /// ui as code elements.
  DecoratedType? _currentLiteralElementType;

  /// The key [DecoratedType] of the innermost map literal being visited, or
  /// `null` if the visitor is not inside any map.
  ///
  /// This is needed to construct the appropriate nullability constraints for
  /// ui as code elements.
  DecoratedType? _currentMapKeyType;

  /// The value [DecoratedType] of the innermost map literal being visited, or
  /// `null` if the visitor is not inside any map.
  ///
  /// This is needed to construct the appropriate nullability constraints for
  /// ui as code elements.
  DecoratedType? _currentMapValueType;

  /// Information about the most recently visited binary expression whose
  /// boolean value could possibly affect nullability analysis.
  _ConditionInfo? _conditionInfo;

  /// The set of nullability nodes that would have to be `nullable` for the code
  /// currently being visited to be reachable.
  ///
  /// Guard variables are attached to the left hand side of any generated
  /// constraints, so that constraints do not take effect if they come from
  /// code that can be proven unreachable by the migration tool.
  final _guards = <NullabilityNode?>[];

  /// The scope of locals (parameters, variables) that are post-dominated by the
  /// current node as we walk the AST. We use a [_ScopedLocalSet] so that outer
  /// scopes may track their post-dominators separately from inner scopes.
  ///
  /// Note that this is not guaranteed to be complete. It is used to make hard
  /// edges on a best-effort basis.
  var _postDominatedLocals = ScopedSet<Element>();

  /// Map whose keys are expressions of the form `a?.b` on the LHS of
  /// assignments, and whose values are the nullability nodes corresponding to
  /// the expression preceding `?.`.  These are needed in order to properly
  /// analyze expressions like `a?.b += c`, since the type of the compound
  /// assignment is nullable if the type of the expression preceding `?.` is
  /// nullable.
  final Map<Expression, NullabilityNode?> _conditionalNodes = {};

  /// If we are visiting a cascade expression, the decorated type of the target
  /// of the cascade.  Otherwise `null`.
  DecoratedType? _currentCascadeTargetType;

  /// While visiting a class declaration, set of class fields that lack
  /// initializers at their declaration sites.
  Set<FieldElement?>? _fieldsNotInitializedAtDeclaration;

  /// While visiting a constructor, set of class fields that lack initializers
  /// at their declaration sites *and* for which we haven't yet found an
  /// initializer in the constructor declaration.
  Set<FieldElement?>? _fieldsNotInitializedByConstructor;

  /// Current nesting depth of [visitNamedType]
  int _typeNameNesting = 0;

  final Set<PromotableElement> _lateHintedLocals = {};

  final Map<Token, HintComment?> _nullCheckHints = {};

  /// Helper that assists us in transforming Iterable methods to their "OrNull"
  /// equivalents.
  final WhereOrNullTransformer _whereOrNullTransformer;

  /// Helper that assists us in transforming calls to `Iterable.where` to
  /// `Iterable.whereNotNull`.
  final WhereNotNullTransformer _whereNotNullTransformer;

  /// Deferred processing that should be performed once we have finished
  /// evaluating the decorated type of a method invocation.
  final Map<MethodInvocation, DecoratedType Function(DecoratedType?)>
      _deferredMethodInvocationProcessing = {};

  /// If we are visiting a local function or closure, the set of local variables
  /// assigned to so far inside it.  Otherwise `null`.
  Set<Element>? _elementsWrittenToInLocalFunction;

  final LibraryElement _library;

  EdgeBuilder(this.typeProvider, this._typeSystem, this._variables, this._graph,
      this.source, this.listener, this._decoratedClassHierarchy, this._library,
      {this.instrumentation})
      : _inheritanceManager = InheritanceManager3(),
        _whereOrNullTransformer =
            WhereOrNullTransformer(typeProvider, _typeSystem),
        _whereNotNullTransformer =
            WhereNotNullTransformer(typeProvider, _typeSystem);

  /// The synthetic element we use as a stand-in for `this` when analyzing
  /// extension methods.
  Element get _extensionThis => DynamicElementImpl.instance;

  /// Gets the decorated type of [element] from [_variables], performing any
  /// necessary substitutions.
  ///
  /// [node] is used as the AST node for the edge origin if any graph edges need
  /// to be created.  [targetType], if provided, indicates the type of the
  /// target (receiver) for a method, getter, or setter invocation.
  /// [targetExpression], if provided, is the expression for the target
  /// (receiver) for a method, getter, or setter invocation.
  DecoratedType getOrComputeElementType(AstNode node, Element element,
      {DecoratedType? targetType, Expression? targetExpression}) {
    Map<TypeParameterElement, DecoratedType?>? substitution;
    Element? baseElement = element.declaration;
    if (targetType != null) {
      var enclosingElement = baseElement!.enclosingElement;
      if (enclosingElement is ClassElement) {
        if (targetType.type.explicitBound is InterfaceType &&
            enclosingElement.typeParameters.isNotEmpty) {
          substitution = _decoratedClassHierarchy!
              .asInstanceOf(targetType, enclosingElement)
              .asSubstitution;
        }
      } else {
        assert(enclosingElement is ExtensionElement);
        final extensionElement = enclosingElement as ExtensionElement;
        // The semantics of calling an extension method or extension property
        // are essentially the same as calling a static function where the
        // receiver is passed as an invisible `this` parameter whose type is the
        // extension's "on" type.  If the extension declaration has type
        // parameters, they behave like inferred type parameters of the static
        // function.
        //
        // So what we need to do is (1) create a set of DecoratedTypes to
        // represent the inferred types of the type parameters, (2) ensure that
        // the receiver type is assignable to "on" type (with those decorated
        // types substituted into it), and (3) substitute those decorated types
        // into the declared type of the extension method or extension property,
        // so that the caller will match up parameter types and the return type
        // appropriately.
        //
        // Taking each step in turn:
        // (1) create a set of decorated types to represent the inferred types
        // of the type parameters.  Note that we must make sure each of these
        // types satisfies its associated bound.
        var typeParameters = extensionElement.typeParameters;
        if (typeParameters.isNotEmpty) {
          var preMigrationSubstitution = (element as Member).substitution.map;
          substitution = {};
          var target = NullabilityNodeTarget.text('extension');
          for (int i = 0; i < typeParameters.length; i++) {
            var typeParameter = typeParameters[i];
            var decoratedTypeArgument = DecoratedType.forImplicitType(
                typeProvider,
                preMigrationSubstitution[typeParameter],
                _graph,
                target.typeArgument(i));
            substitution[typeParameter] = decoratedTypeArgument;
            var edgeOrigin =
                InferredTypeParameterInstantiationOrigin(source, node);
            _checkAssignment(edgeOrigin, FixReasonTarget.root,
                source: decoratedTypeArgument,
                destination:
                    _variables!.decoratedTypeParameterBound(typeParameter)!,
                hard: true);
          }
        }
        // (2) ensure that the receiver type is assignable to "on" type (with
        // those decorated types substituted into it)
        var onType = _variables!.decoratedElementType(extensionElement);
        if (substitution != null) {
          onType = onType.substitute(substitution);
        }
        _checkAssignment(InferredTypeParameterInstantiationOrigin(source, node),
            FixReasonTarget.root,
            source: targetType,
            destination: onType,
            hard: targetExpression == null ||
                _isReferenceInScope(targetExpression));
        // (3) substitute those decorated types into the declared type of the
        // extension method or extension property, so that the caller will match
        // up parameter types and the return type appropriately.
        //
        // There's nothing more we need to do here.  The substitution below
        // will do the job.
      }
    }
    DecoratedType decoratedBaseType;
    if (baseElement is PropertyAccessorElement &&
        baseElement.isSynthetic &&
        !baseElement.variable.isSynthetic) {
      var variable = baseElement.variable;
      var decoratedElementType = _variables!.decoratedElementType(variable);
      if (baseElement.isGetter) {
        var target = NullabilityNodeTarget.text('getter function');
        decoratedBaseType = DecoratedType(
            baseElement.type, NullabilityNode.forInferredType(target),
            returnType: decoratedElementType);
      } else {
        assert(baseElement.isSetter);
        var target = NullabilityNodeTarget.text('setter function');
        decoratedBaseType = DecoratedType(
            baseElement.type, NullabilityNode.forInferredType(target),
            positionalParameters: [decoratedElementType],
            returnType: DecoratedType(VoidTypeImpl.instance,
                NullabilityNode.forInferredType(target.returnType())));
      }
    } else {
      decoratedBaseType = _variables!.decoratedElementType(baseElement!);
    }
    if (substitution != null) {
      return decoratedBaseType.substitute(substitution);
    } else {
      return decoratedBaseType;
    }
  }

  @override
  // TODO(srawlins): Theoretically, edges should be connected between arguments
  // and parameters, as in an instance creation. It is quite rare though, to
  // declare a class and use it as an annotation in the same package.
  DecoratedType? visitAnnotation(Annotation node) {
    var previousFlowAnalysis = _flowAnalysis;
    var previousAssignedVariables = _assignedVariables;
    if (_flowAnalysis == null) {
      _assignedVariables = AssignedVariables();
      // Note: we are using flow analysis to help us track true nullabilities;
      // it's not necessary to replicate old bugs.  So we pass `true` for
      // `respectImplicitlyTypedVarInitializers`.
      _flowAnalysis = FlowAnalysis<AstNode, Statement, Expression,
              PromotableElement, DecoratedType>(
          DecoratedTypeOperations(_typeSystem, _variables, _graph),
          _assignedVariables!,
          respectImplicitlyTypedVarInitializers: true);
    }
    try {
      _dispatch(node.constructorName);
      _dispatchList(node.arguments?.arguments);
    } finally {
      _flowAnalysis = previousFlowAnalysis;
      _assignedVariables = previousAssignedVariables;
    }
    annotationVisited(node);
    return null;
  }

  @override
  DecoratedType visitAsExpression(AsExpression node) {
    if (BestPracticesVerifier.isUnnecessaryCast(
        node, _typeSystem as TypeSystemImpl)) {
      _variables!.recordUnnecessaryCast(source, node);
    }
    _dispatch(node.type);
    final typeNode = _variables!.decoratedTypeAnnotation(source, node.type);
    _handleAssignment(node.expression, destinationType: typeNode);
    _flowAnalysis!.asExpression_end(node.expression, typeNode);
    return typeNode;
  }

  @override
  DecoratedType? visitAssertInitializer(AssertInitializer node) {
    _flowAnalysis!.assert_begin();
    _checkExpressionNotNull(node.condition);
    if (identical(_conditionInfo?.condition, node.condition)) {
      var intentNode = _conditionInfo!.trueDemonstratesNonNullIntent;
      if (intentNode != null && _conditionInfo!.postDominatingIntent!) {
        _graph.makeNonNullable(_conditionInfo!.trueDemonstratesNonNullIntent,
            NonNullAssertionOrigin(source, node));
      }
    }
    _flowAnalysis!.assert_afterCondition(node.condition);
    _dispatch(node.message);
    _flowAnalysis!.assert_end();
    return null;
  }

  @override
  DecoratedType? visitAssertStatement(AssertStatement node) {
    _flowAnalysis!.assert_begin();
    _checkExpressionNotNull(node.condition);
    if (identical(_conditionInfo?.condition, node.condition)) {
      var intentNode = _conditionInfo!.trueDemonstratesNonNullIntent;
      if (intentNode != null && _conditionInfo!.postDominatingIntent!) {
        _graph.makeNonNullable(_conditionInfo!.trueDemonstratesNonNullIntent,
            NonNullAssertionOrigin(source, node));
      }
    }
    _flowAnalysis!.assert_afterCondition(node.condition);
    _dispatch(node.message);
    _flowAnalysis!.assert_end();
    return null;
  }

  @override
  DecoratedType? visitAssignmentExpression(AssignmentExpression node) {
    bool isQuestionAssign = false;
    bool isCompound = false;
    if (node.operator.type == TokenType.QUESTION_QUESTION_EQ) {
      isQuestionAssign = true;
    } else if (node.operator.type != TokenType.EQ) {
      isCompound = true;
    }

    var sourceIsSetupCall = false;
    if (node.leftHandSide is SimpleIdentifier &&
        _isCurrentFunctionExpressionFoundInTestSetUpCall()) {
      var assignee =
          getWriteOrReadElement(node.leftHandSide as SimpleIdentifier)!;
      var enclosingElementOfCurrentFunction =
          _currentFunctionExpression!.declaredElement!.enclosingElement;
      if (enclosingElementOfCurrentFunction == assignee.enclosingElement) {
        // [node]'s enclosing function is a function expression passed directly
        // to a call to the test package's `setUp` function, and [node] is an
        // assignment to a variable declared in the same scope as the call to
        // `setUp`.
        sourceIsSetupCall = true;
      }
    }

    var expressionType = _handleAssignment(node.rightHandSide,
        assignmentExpression: node,
        compoundOperatorInfo: isCompound ? node : null,
        questionAssignNode: isQuestionAssign ? node : null,
        sourceIsSetupCall: sourceIsSetupCall);
    var conditionalNode = _conditionalNodes[node.leftHandSide];
    if (conditionalNode != null) {
      expressionType = expressionType!.withNode(
          NullabilityNode.forLUB(conditionalNode, expressionType.node));
      _variables!.recordDecoratedExpressionType(node, expressionType);
    }

    return expressionType;
  }

  @override
  DecoratedType visitAwaitExpression(AwaitExpression node) {
    var expressionType = _dispatch(node.expression)!;
    var type = expressionType.type!;
    if (type.isDartCoreNull) {
      // Nothing to do; awaiting `null` produces `null`.
    } else if (_typeSystem.isSubtypeOf(type, typeProvider.futureDynamicType)) {
      expressionType = _decoratedClassHierarchy!
          .asInstanceOf(expressionType, typeProvider.futureElement)
          .typeArguments[0]!;
    } else if (type.isDartAsyncFutureOr) {
      expressionType = expressionType.typeArguments[0]!;
    }
    return expressionType;
  }

  @override
  DecoratedType visitBinaryExpression(BinaryExpression node) {
    var operatorType = node.operator.type;
    var leftOperand = node.leftOperand;
    var rightOperand = node.rightOperand;
    if (operatorType == TokenType.EQ_EQ || operatorType == TokenType.BANG_EQ) {
      var leftType = _dispatch(leftOperand)!;
      _graph.connectDummy(leftType.node, DummyOrigin(source, node));
      var equalityInfo =
          _flowAnalysis!.equalityOperand_end(leftOperand, leftType);
      var rightType = _dispatch(rightOperand)!;
      _graph.connectDummy(rightType.node, DummyOrigin(source, node));
      bool notEqual = operatorType == TokenType.BANG_EQ;
      _flowAnalysis!.equalityOperation_end(node, equalityInfo,
          _flowAnalysis!.equalityOperand_end(rightOperand, rightType),
          notEqual: notEqual);

      void buildNullConditionInfo(NullLiteral nullLiteral,
          Expression otherOperand, NullabilityNode? otherNode) {
        assert(nullLiteral != otherOperand);
        // TODO(paulberry): only set falseChecksNonNull in unconditional
        // control flow
        // TODO(paulberry): figure out what the rules for isPure should be.
        bool isPure = otherOperand is SimpleIdentifier;
        var conditionInfo = _ConditionInfo(node,
            isPure: isPure,
            postDominatingIntent: _isReferenceInScope(otherOperand),
            trueGuard: otherNode,
            falseDemonstratesNonNullIntent: otherNode);
        _conditionInfo = notEqual ? conditionInfo.not(node) : conditionInfo;
      }

      if (rightOperand is NullLiteral) {
        buildNullConditionInfo(rightOperand, leftOperand, leftType.node);
      } else if (leftOperand is NullLiteral) {
        buildNullConditionInfo(leftOperand, rightOperand, rightType.node);
      }

      return _makeNonNullableBoolType(node);
    } else if (operatorType == TokenType.AMPERSAND_AMPERSAND ||
        operatorType == TokenType.BAR_BAR) {
      bool isAnd = operatorType == TokenType.AMPERSAND_AMPERSAND;
      _flowAnalysis!.logicalBinaryOp_begin();
      _checkExpressionNotNull(leftOperand);
      _flowAnalysis!
          .logicalBinaryOp_rightBegin(node.leftOperand, node, isAnd: isAnd);
      _postDominatedLocals.doScoped(
          action: () => _checkExpressionNotNull(rightOperand));
      _flowAnalysis!.logicalBinaryOp_end(node, rightOperand, isAnd: isAnd);
      return _makeNonNullableBoolType(node);
    } else if (operatorType == TokenType.QUESTION_QUESTION) {
      DecoratedType expressionType;
      var leftType = _dispatch(leftOperand)!;
      _flowAnalysis!.ifNullExpression_rightBegin(node.leftOperand, leftType);
      try {
        _guards.add(leftType.node);
        DecoratedType? rightType;
        _postDominatedLocals.doScoped(action: () {
          rightType = _dispatch(rightOperand);
        });
        var ifNullNode = NullabilityNode.forIfNotNull(node);
        expressionType = _decorateUpperOrLowerBound(
            node, node.staticType, leftType, rightType!, true,
            node: ifNullNode);
        _connect(rightType!.node, expressionType.node,
            IfNullOrigin(source, node), null);
      } finally {
        _flowAnalysis!.ifNullExpression_end();
        _guards.removeLast();
      }
      _variables!.recordDecoratedExpressionType(node, expressionType);
      return expressionType;
    } else if (operatorType.isUserDefinableOperator) {
      var targetType = _checkExpressionNotNull(leftOperand);
      var callee = node.staticElement;
      if (callee == null) {
        _dispatch(rightOperand);
        return _makeNullableDynamicType(node);
      } else {
        var calleeType = getOrComputeElementType(node, callee,
            targetType: targetType, targetExpression: leftOperand);
        assert(calleeType.positionalParameters!.isNotEmpty); // TODO(paulberry)
        _handleAssignment(rightOperand,
            destinationType: calleeType.positionalParameters![0]);
        return _fixNumericTypes(calleeType.returnType!, node.staticType);
      }
    } else {
      // TODO(paulberry)
      _dispatch(leftOperand);
      _dispatch(rightOperand);
      _unimplemented(
          node, 'Binary expression with operator ${node.operator.lexeme}');
    }
  }

  @override
  DecoratedType visitBooleanLiteral(BooleanLiteral node) {
    _flowAnalysis!.booleanLiteral(node, node.value);
    return _makeNonNullLiteralType(node);
  }

  @override
  DecoratedType? visitBreakStatement(BreakStatement node) {
    _flowAnalysis!.handleBreak(FlowAnalysisHelper.getLabelTarget(
        node, node.label?.staticElement as LabelElement?)!);
    // Later statements no longer post-dominate the declarations because we
    // exited (or, in parent scopes, conditionally exited).
    // TODO(mfairhurst): don't clear post-dominators beyond the current loop.
    _postDominatedLocals.clearEachScope();

    return null;
  }

  @override
  DecoratedType? visitCascadeExpression(CascadeExpression node) {
    var oldCascadeTargetType = _currentCascadeTargetType;
    try {
      _currentCascadeTargetType = _checkExpressionNotNull(node.target);
      _dispatchList(node.cascadeSections);
      return _currentCascadeTargetType;
    } finally {
      _currentCascadeTargetType = oldCascadeTargetType;
    }
  }

  @override
  DecoratedType? visitCatchClause(CatchClause node) {
    _flowAnalysis!.tryCatchStatement_catchBegin(
        node.exceptionParameter?.staticElement as PromotableElement?,
        node.stackTraceParameter?.staticElement as PromotableElement?);
    _dispatch(node.exceptionType);
    // The catch clause may not execute, so create a new scope for
    // post-dominators.
    _postDominatedLocals.doScoped(action: () => _dispatch(node.body));
    _flowAnalysis!.tryCatchStatement_catchEnd();
    return null;
  }

  @override
  DecoratedType? visitClassDeclaration(ClassDeclaration node) {
    visitClassOrMixinOrExtensionDeclaration(node);
    _dispatch(node.extendsClause);
    _dispatch(node.implementsClause);
    _dispatch(node.withClause);
    _dispatch(node.typeParameters);
    return null;
  }

  DecoratedType? visitClassOrMixinOrExtensionDeclaration(
      CompilationUnitMember node) {
    assert(node is ClassOrMixinDeclaration || node is ExtensionDeclaration);
    try {
      _currentClassOrExtension = node.declaredElement;
      var members = node is ClassOrMixinDeclaration
          ? node.members
          : (node as ExtensionDeclaration).members;

      _fieldsNotInitializedAtDeclaration = {
        for (var member in members)
          if (member is FieldDeclaration &&
              _variables!.getLateHint(source, member.fields) == null)
            for (var field in member.fields.variables)
              if (!field.declaredElement!.isStatic && field.initializer == null)
                (field.declaredElement as FieldElement?)
      };
      if (_currentClassOrExtension is ClassElement &&
          (_currentClassOrExtension as ClassElement)
                  .unnamedConstructor
                  ?.isSynthetic ==
              true) {
        _handleUninitializedFields(node, _fieldsNotInitializedAtDeclaration!);
      }
      _dispatchList(node.metadata);
      _dispatchList(members);
      _fieldsNotInitializedAtDeclaration = null;
    } finally {
      _currentClassOrExtension = null;
    }
    return null;
  }

  @override
  DecoratedType? visitClassTypeAlias(ClassTypeAlias node) {
    _dispatch(node.superclass);
    _dispatch(node.implementsClause);
    _dispatch(node.withClause);
    var classElement = node.declaredElement!;
    var supertype = classElement.supertype!;
    var superElement = supertype.element;
    for (var constructorElement in classElement.constructors) {
      assert(constructorElement.isSynthetic);
      var superConstructorElement =
          superElement.getNamedConstructor(constructorElement.name)!;
      var constructorDecoratedType = _variables!
          .decoratedElementType(constructorElement)
          .substitute(_decoratedClassHierarchy!
              .getDecoratedSupertype(classElement, superElement)
              .asSubstitution);
      var superConstructorDecoratedType =
          _variables!.decoratedElementType(superConstructorElement);
      var origin = ImplicitMixinSuperCallOrigin(source, node);
      _linkDecoratedTypeParameters(
          constructorDecoratedType, superConstructorDecoratedType, origin,
          isUnion: true);
    }
    return null;
  }

  @override
  DecoratedType? visitComment(Comment node) {
    // Ignore comments.
    return null;
  }

  @override
  DecoratedType visitConditionalExpression(ConditionalExpression node) {
    _flowAnalysis!.conditional_conditionBegin();
    _checkExpressionNotNull(node.condition);
    NullabilityNode? trueGuard;
    NullabilityNode? falseGuard;
    if (identical(_conditionInfo?.condition, node.condition)) {
      trueGuard = _conditionInfo!.trueGuard;
      falseGuard = _conditionInfo!.falseGuard;
      _variables!.recordConditionalDiscard(source, node,
          ConditionalDiscard(trueGuard, falseGuard, _conditionInfo!.isPure));
    }

    DecoratedType? thenType;
    DecoratedType? elseType;

    // Post-dominators diverge as we branch in the conditional.
    // Note: we don't have to create a scope for each branch because they can't
    // define variables.
    _postDominatedLocals.doScoped(action: () {
      _flowAnalysis!.conditional_thenBegin(node.condition, node);
      if (trueGuard != null) {
        _guards.add(trueGuard);
      }
      try {
        thenType = _dispatch(node.thenExpression);
        if (trueGuard != null) {
          thenType = thenType!.withNode(
              _nullabilityNodeForGLB(node, thenType!.node!, trueGuard));
        }
      } finally {
        if (trueGuard != null) {
          _guards.removeLast();
        }
      }
      _flowAnalysis!.conditional_elseBegin(node.thenExpression);
      if (falseGuard != null) {
        _guards.add(falseGuard);
      }
      try {
        elseType = _dispatch(node.elseExpression);
        if (falseGuard != null) {
          elseType = elseType!.withNode(
              _nullabilityNodeForGLB(node, elseType!.node!, falseGuard));
        }
      } finally {
        if (falseGuard != null) {
          _guards.removeLast();
        }
      }
      _flowAnalysis!.conditional_end(node, node.elseExpression);
    });

    var overallType = _decorateUpperOrLowerBound(
        node, node.staticType, thenType!, elseType!, true);
    _variables!.recordDecoratedExpressionType(node, overallType);
    return overallType;
  }

  @override
  DecoratedType? visitConstructorDeclaration(ConstructorDeclaration node) {
    _fieldsNotInitializedByConstructor =
        _fieldsNotInitializedAtDeclaration!.toSet();
    _dispatch(node.redirectedConstructor?.type.typeArguments);
    _handleExecutableDeclaration(
        node,
        node.declaredElement!,
        node.metadata,
        null,
        node.parameters,
        node.initializers,
        node.body,
        node.redirectedConstructor);
    _fieldsNotInitializedByConstructor = null;
    return null;
  }

  @override
  DecoratedType? visitConstructorFieldInitializer(
      ConstructorFieldInitializer node) {
    _fieldsNotInitializedByConstructor!.remove(node.fieldName.staticElement);
    _handleAssignment(node.expression,
        destinationType:
            getOrComputeElementType(node, node.fieldName.staticElement!));
    return null;
  }

  @override
  DecoratedType? visitContinueStatement(ContinueStatement node) {
    _flowAnalysis!.handleContinue(FlowAnalysisHelper.getLabelTarget(
        node, node.label?.staticElement as LabelElement?)!);
    // Later statements no longer post-dominate the declarations because we
    // exited (or, in parent scopes, conditionally exited).
    // TODO(mfairhurst): don't clear post-dominators beyond the current loop.
    _postDominatedLocals.clearEachScope();

    return null;
  }

  @override
  DecoratedType? visitDefaultFormalParameter(DefaultFormalParameter node) {
    _dispatch(node.parameter);
    var defaultValue = node.defaultValue;
    var declaredElement = node.declaredElement;
    if (defaultValue == null) {
      if (declaredElement!.hasRequired) {
        // Nothing to do; the implicit default value of `null` will never be
        // reached.
      } else if (_variables!.getRequiredHint(source, node) != null) {
        // Nothing to do; assume the implicit default value of `null` will never
        // be reached.
      } else {
        var enclosingElement = declaredElement.enclosingElement;
        if (enclosingElement is ConstructorElement &&
            enclosingElement.isFactory &&
            enclosingElement.redirectedConstructor != null) {
          // Redirecting factory constructors inherit their parameters' default
          // values from the constructors they redirect to, so the lack of a
          // default value doesn't mean the parameter has to be nullable.
        } else {
          _graph.makeNullable(
              getOrComputeElementType(node, declaredElement).node!,
              OptionalFormalParameterOrigin(source, node));
        }
      }
    } else {
      _handleAssignment(defaultValue,
          destinationType: getOrComputeElementType(node, declaredElement!),
          fromDefaultValue: true);
    }
    return null;
  }

  @override
  DecoratedType? visitDoStatement(DoStatement node) {
    _flowAnalysis!.doStatement_bodyBegin(node);
    _dispatch(node.body);
    _flowAnalysis!.doStatement_conditionBegin();
    _checkExpressionNotNull(node.condition);
    _flowAnalysis!.doStatement_end(node.condition);
    return null;
  }

  @override
  DecoratedType visitDoubleLiteral(DoubleLiteral node) {
    return _makeNonNullLiteralType(node);
  }

  @override
  DecoratedType? visitExpressionFunctionBody(ExpressionFunctionBody node) {
    if (_currentFunctionType == null) {
      _unimplemented(
          node,
          'ExpressionFunctionBody with no current function '
          '(parent is ${node.parent.runtimeType})');
    }
    _handleAssignment(node.expression,
        destinationType: _currentFunctionType!.returnType,
        wrapFuture: node.isAsynchronous);
    return null;
  }

  @override
  DecoratedType visitExpressionStatement(ExpressionStatement node) {
    var decoratedType = _dispatch(node.expression)!;
    _graph.connectDummy(decoratedType.node, DummyOrigin(source, node));
    return decoratedType;
  }

  DecoratedType? visitExtensionDeclaration(ExtensionDeclaration node) {
    _dispatch(node.typeParameters);
    _dispatch(node.extendedType);
    _currentExtendedType =
        _variables!.decoratedTypeAnnotation(source, node.extendedType);
    visitClassOrMixinOrExtensionDeclaration(node);
    _currentExtendedType = null;
    return null;
  }

  @override
  DecoratedType? visitExtensionOverride(ExtensionOverride node) {
    return _dispatch(node.argumentList.arguments.single);
  }

  @override
  DecoratedType? visitFieldFormalParameter(FieldFormalParameter node) {
    _dispatchList(node.metadata);
    _dispatch(node.parameters);
    var parameterElement = node.declaredElement as FieldFormalParameterElement;
    var parameterType = _variables!.decoratedElementType(parameterElement);
    var field = parameterElement.field;
    if (field != null) {
      _fieldsNotInitializedByConstructor!.remove(field);
      var fieldType = _variables!.decoratedElementType(field);
      var origin = FieldFormalParameterOrigin(source, node);
      if (node.type == null) {
        _linkDecoratedTypes(parameterType, fieldType, origin, isUnion: false);
        _checkAssignment(origin, FixReasonTarget.root,
            source: fieldType, destination: parameterType, hard: false);
      } else {
        _dispatch(node.type);
        _checkAssignment(origin, FixReasonTarget.root,
            source: parameterType, destination: fieldType, hard: true);
      }
    }

    return null;
  }

  @override
  DecoratedType? visitForElement(ForElement node) {
    _handleForLoopParts(node, node.forLoopParts, node.body,
        (body) => _handleCollectionElement(body as CollectionElement));
    return null;
  }

  @override
  DecoratedType? visitForStatement(ForStatement node) {
    _handleForLoopParts(
        node, node.forLoopParts, node.body, (body) => _dispatch(body));
    return null;
  }

  @override
  DecoratedType? visitFunctionDeclaration(FunctionDeclaration node) {
    _dispatchList(node.metadata);
    _dispatch(node.returnType);
    if (_flowAnalysis != null) {
      // This is a local function.
      var previousPostDominatedLocals = _postDominatedLocals;
      var previousElementsWrittenToInLocalFunction =
          _elementsWrittenToInLocalFunction;
      try {
        _elementsWrittenToInLocalFunction = {};
        _postDominatedLocals = ScopedSet<Element>();
        _flowAnalysis!.functionExpression_begin(node);
        _dispatch(node.functionExpression);
        _flowAnalysis!.functionExpression_end();
      } finally {
        for (var element in _elementsWrittenToInLocalFunction!) {
          previousElementsWrittenToInLocalFunction?.add(element);
          previousPostDominatedLocals.removeFromAllScopes(element);
        }
        _elementsWrittenToInLocalFunction =
            previousElementsWrittenToInLocalFunction;
        _postDominatedLocals = previousPostDominatedLocals;
      }
    } else {
      _createFlowAnalysis(node, node.functionExpression.parameters);
      // Initialize a new postDominator scope that contains only the parameters.
      try {
        _dispatch(node.functionExpression);
        _flowAnalysis!.finish();
      } finally {
        _flowAnalysis = null;
        _assignedVariables = null;
      }
      var declaredElement = node.declaredElement;
      if (declaredElement is PropertyAccessorElement) {
        if (declaredElement.isGetter) {
          var setter = declaredElement.correspondingSetter;
          if (setter != null) {
            _handleGetterSetterCorrespondence(
                node, null, declaredElement, setter.declaration);
          }
        } else {
          assert(declaredElement.isSetter);
          var getter = declaredElement.correspondingGetter;
          if (getter != null) {
            _handleGetterSetterCorrespondence(
                node, null, getter.declaration, declaredElement);
          }
        }
      }
    }
    return null;
  }

  @override
  DecoratedType? visitFunctionExpression(FunctionExpression node) {
    // TODO(mfairhurst): enable edge builder "_insideFunction" hard edge tests.
    _dispatch(node.parameters);
    _dispatch(node.typeParameters);
    if (node.parent is! FunctionDeclaration) {
      _flowAnalysis!.functionExpression_begin(node);
    }
    _addParametersToFlowAnalysis(node.parameters);
    var previousFunction = _currentFunctionExpression;
    var previousFunctionType = _currentFunctionType;
    var previousFieldFormals = _currentFieldFormals;
    _currentFunctionExpression = node;
    _currentFunctionType =
        _variables!.decoratedElementType(node.declaredElement!);
    _currentFieldFormals = const {};
    var previousPostDominatedLocals = _postDominatedLocals;
    var previousElementsWrittenToInLocalFunction =
        _elementsWrittenToInLocalFunction;
    try {
      if (node.parent is! FunctionDeclaration) {
        _elementsWrittenToInLocalFunction = {};
      }
      _postDominatedLocals = ScopedSet<Element>();
      _postDominatedLocals.doScoped(
          elements: node.declaredElement!.parameters,
          action: () => _dispatch(node.body));
      _variables!.recordDecoratedExpressionType(node, _currentFunctionType);
      return _currentFunctionType;
    } finally {
      if (node.parent is! FunctionDeclaration) {
        _flowAnalysis!.functionExpression_end();
        for (var element in _elementsWrittenToInLocalFunction!) {
          previousElementsWrittenToInLocalFunction?.add(element);
          previousPostDominatedLocals.removeFromAllScopes(element);
        }
        _elementsWrittenToInLocalFunction =
            previousElementsWrittenToInLocalFunction;
      }
      _currentFunctionType = previousFunctionType;
      _currentFieldFormals = previousFieldFormals;
      _currentFunctionExpression = previousFunction;
      _postDominatedLocals = previousPostDominatedLocals;
    }
  }

  @override
  DecoratedType? visitFunctionExpressionInvocation(
      FunctionExpressionInvocation node) {
    final argumentList = node.argumentList;
    final typeArguments = node.typeArguments;
    _dispatch(typeArguments);
    DecoratedType calleeType = _checkExpressionNotNull(node.function);
    DecoratedType? result;
    if (calleeType.type is FunctionType) {
      result = _handleInvocationArguments(node, argumentList.arguments,
          typeArguments, node.typeArgumentTypes, calleeType, null,
          invokeType: node.staticInvokeType);
    } else {
      // Invocation of type `dynamic` or `Function`.
      _dispatch(argumentList);
      result = _makeNullableDynamicType(node);
    }
    return result;
  }

  @override
  DecoratedType? visitIfElement(IfElement node) {
    _flowAnalysis!.ifStatement_conditionBegin();
    _checkExpressionNotNull(node.condition);
    _flowAnalysis!.ifStatement_thenBegin(node.condition, node);
    NullabilityNode? trueGuard;
    NullabilityNode? falseGuard;
    if (identical(_conditionInfo?.condition, node.condition)) {
      trueGuard = _conditionInfo!.trueGuard;
      falseGuard = _conditionInfo!.falseGuard;
      _variables!.recordConditionalDiscard(source, node,
          ConditionalDiscard(trueGuard, falseGuard, _conditionInfo!.isPure));
    }
    if (trueGuard != null) {
      _guards.add(trueGuard);
    }
    try {
      _postDominatedLocals.doScoped(
          action: () => _handleCollectionElement(node.thenElement));
    } finally {
      if (trueGuard != null) {
        _guards.removeLast();
      }
    }
    if (node.elseElement != null) {
      _flowAnalysis!.ifStatement_elseBegin();
      if (falseGuard != null) {
        _guards.add(falseGuard);
      }
      try {
        _postDominatedLocals.doScoped(
            action: () => _handleCollectionElement(node.elseElement));
      } finally {
        if (falseGuard != null) {
          _guards.removeLast();
        }
      }
    }
    _flowAnalysis!.ifStatement_end(node.elseElement != null);
    return null;
  }

  @override
  DecoratedType? visitIfStatement(IfStatement node) {
    _flowAnalysis!.ifStatement_conditionBegin();
    _checkExpressionNotNull(node.condition);
    NullabilityNode? trueGuard;
    NullabilityNode? falseGuard;
    if (identical(_conditionInfo?.condition, node.condition)) {
      trueGuard = _conditionInfo!.trueGuard;
      falseGuard = _conditionInfo!.falseGuard;
      _variables!.recordConditionalDiscard(source, node,
          ConditionalDiscard(trueGuard, falseGuard, _conditionInfo!.isPure));
    }
    if (trueGuard != null) {
      _guards.add(trueGuard);
    }
    try {
      _flowAnalysis!.ifStatement_thenBegin(node.condition, node);
      // We branched, so create a new scope for post-dominators.
      _postDominatedLocals.doScoped(
          action: () => _dispatch(node.thenStatement));
    } finally {
      if (trueGuard != null) {
        _guards.removeLast();
      }
    }
    if (falseGuard != null) {
      _guards.add(falseGuard);
    }
    var elseStatement = node.elseStatement;
    try {
      if (elseStatement != null) {
        _flowAnalysis!.ifStatement_elseBegin();
        // We branched, so create a new scope for post-dominators.
        _postDominatedLocals.doScoped(
            action: () => _dispatch(node.elseStatement));
      }
    } finally {
      _flowAnalysis!.ifStatement_end(elseStatement != null);
      if (falseGuard != null) {
        _guards.removeLast();
      }
    }
    return null;
  }

  @override
  DecoratedType? visitImplicitCallReference(ImplicitCallReference node) {
    return _handlePropertyAccessGeneralized(
        node: node,
        target: node.expression,
        propertyName: 'call',
        isNullAware: false,
        isCascaded: false,
        inSetterContext: false,
        callee: node.staticElement);
  }

  @override
  DecoratedType? visitIndexExpression(IndexExpression node) {
    DecoratedType? targetType;
    var target = node.target;
    if (node.isCascaded) {
      targetType = _currentCascadeTargetType;
    } else if (target != null) {
      targetType = _checkExpressionNotNull(target);
    }
    var callee = getWriteOrReadElement(node);
    DecoratedType? result;
    if (callee == null) {
      // Dynamic dispatch.  The return type is `dynamic`.
      // TODO(paulberry): would it be better to assume a return type of `Never`
      // so that we don't unnecessarily propagate nullabilities everywhere?
      result = _makeNullableDynamicType(node);
    } else {
      var calleeType = getOrComputeElementType(node, callee,
          targetType: targetType, targetExpression: target);
      // TODO(paulberry): substitute if necessary
      _handleAssignment(node.index,
          destinationType: calleeType.positionalParameters![0]);
      if (node.inSetterContext()) {
        result = calleeType.positionalParameters![1];
      } else {
        result = calleeType.returnType;
      }
    }
    return result;
  }

  @override
  DecoratedType visitInstanceCreationExpression(
      InstanceCreationExpression node) {
    var callee = node.constructorName.staticElement!;
    var typeParameters = callee.enclosingElement.typeParameters;
    Iterable<DartType?> typeArgumentTypes;
    List<DecoratedType> decoratedTypeArguments;
    var typeArguments = node.constructorName.type.typeArguments;
    late List<EdgeOrigin> parameterEdgeOrigins;
    var target =
        NullabilityNodeTarget.text('constructed type').withCodeRef(node);
    if (typeArguments != null) {
      _dispatch(typeArguments);
      typeArgumentTypes = typeArguments.arguments.map((t) => t.type);
      decoratedTypeArguments = typeArguments.arguments
          .map((t) => _variables!.decoratedTypeAnnotation(source, t))
          .toList();
      parameterEdgeOrigins = typeArguments.arguments
          .map((typeAnn) => TypeParameterInstantiationOrigin(source, typeAnn))
          .toList();
    } else {
      var staticType = node.staticType;
      if (staticType is InterfaceType) {
        typeArgumentTypes = staticType.typeArguments;
        int index = 0;
        decoratedTypeArguments = typeArgumentTypes.map((t) {
          return DecoratedType.forImplicitType(
              typeProvider, t, _graph, target.typeArgument(index++));
        }).toList();
        instrumentation?.implicitTypeArguments(
            source, node, decoratedTypeArguments);
        parameterEdgeOrigins = List.filled(typeArgumentTypes.length,
            InferredTypeParameterInstantiationOrigin(source, node));
      } else {
        // Note: this could happen if the code being migrated has errors.
        typeArgumentTypes = const [];
        decoratedTypeArguments = const [];
      }
    }

    if (node.staticType!.isDartCoreList &&
        callee.name == '' &&
        node.argumentList.arguments.length == 1) {
      _graph.connect(_graph.always, decoratedTypeArguments[0].node!,
          ListLengthConstructorOrigin(source, node));
    }

    var nullabilityNode = NullabilityNode.forInferredType(target);
    _graph.makeNonNullable(
        nullabilityNode, InstanceCreationOrigin(source, node));
    var createdType = DecoratedType(node.staticType, nullabilityNode,
        typeArguments: decoratedTypeArguments);
    var calleeType =
        getOrComputeElementType(node, callee, targetType: createdType);
    for (var i = 0; i < decoratedTypeArguments.length; ++i) {
      _checkAssignment(parameterEdgeOrigins.elementAt(i),
          FixReasonTarget.root.typeArgument(i),
          source: decoratedTypeArguments[i],
          destination:
              _variables!.decoratedTypeParameterBound(typeParameters[i])!,
          hard: true);
    }
    _handleInvocationArguments(node, node.argumentList.arguments, typeArguments,
        typeArgumentTypes, calleeType, typeParameters);
    return createdType;
  }

  @override
  DecoratedType visitIntegerLiteral(IntegerLiteral node) {
    return _makeNonNullLiteralType(node);
  }

  @override
  DecoratedType visitIsExpression(IsExpression node) {
    var expression = node.expression;
    var expressionNode = _dispatch(expression)!.node;
    var type = node.type;
    _dispatch(type);
    var decoratedType = _variables!.decoratedTypeAnnotation(source, type);
    // The main type of the is check historically could not be nullable.
    // Making it nullable could change runtime behavior.
    _graph.makeNonNullable(
        decoratedType.node, IsCheckMainTypeOrigin(source, type));
    _conditionInfo = _ConditionInfo(node,
        isPure: expression is SimpleIdentifier,
        postDominatingIntent: _isReferenceInScope(expression),
        trueDemonstratesNonNullIntent: expressionNode);
    if (node.notOperator != null) {
      _conditionInfo = _conditionInfo!.not(node);
    }
    if (!_assumeNonNullabilityInCasts) {
      // TODO(mfairhurst): wire this to handleDowncast if we do not assume
      // nullability.
      assert(false);
    }
    _flowAnalysis!.isExpression_end(
        node, expression, node.notOperator != null, decoratedType);
    return _makeNonNullableBoolType(node);
  }

  @override
  DecoratedType? visitLabel(Label node) {
    // Labels are identifiers but they don't have types so we don't need to
    // visit them directly.
    return null;
  }

  @override
  DecoratedType? visitLibraryDirective(LibraryDirective node) {
    // skip directives, but not their metadata
    _dispatchList(node.metadata);
    return null;
  }

  @override
  DecoratedType visitListLiteral(ListLiteral node) {
    final previousLiteralType = _currentLiteralElementType;
    try {
      var listType = node.staticType as InterfaceType?;
      if (node.typeArguments == null) {
        var target =
            NullabilityNodeTarget.text('list element type').withCodeRef(node);
        var elementType = DecoratedType.forImplicitType(
            typeProvider, listType!.typeArguments[0], _graph, target);
        instrumentation?.implicitTypeArguments(source, node, [elementType]);
        _currentLiteralElementType = elementType;
      } else {
        _dispatch(node.typeArguments);
        _currentLiteralElementType = _variables!
            .decoratedTypeAnnotation(source, node.typeArguments!.arguments[0]);
      }
      node.elements.forEach(_handleCollectionElement);
      return _makeNonNullLiteralType(node,
          typeArguments: [_currentLiteralElementType]);
    } finally {
      _currentLiteralElementType = previousLiteralType;
    }
  }

  @override
  DecoratedType? visitMapLiteralEntry(MapLiteralEntry node) {
    assert(_currentMapKeyType != null);
    assert(_currentMapValueType != null);
    _handleAssignment(node.key, destinationType: _currentMapKeyType);
    _handleAssignment(node.value, destinationType: _currentMapValueType);
    return null;
  }

  @override
  DecoratedType? visitMethodDeclaration(MethodDeclaration node) {
    if (BuiltValueTransformer.findNullableAnnotation(node) != null) {
      _graph.makeNullable(
          _variables!
              .decoratedElementType(node.declaredElement!.declaration)
              .returnType!
              .node!,
          BuiltValueNullableOrigin(source, node));
    }
    _handleExecutableDeclaration(node, node.declaredElement!, node.metadata,
        node.returnType, node.parameters, null, node.body, null);
    _dispatch(node.typeParameters);
    return null;
  }

  @override
  DecoratedType? visitMethodInvocation(MethodInvocation node) {
    DecoratedType? targetType;
    var target = node.target;
    bool isNullAware = node.isNullAware;
    var callee = node.methodName.staticElement;
    bool calleeIsStatic = callee is ExecutableElement && callee.isStatic;
    _dispatch(node.typeArguments);

    if (node.isCascaded) {
      targetType = _currentCascadeTargetType;
    } else if (target != null) {
      if (_isPrefix(target)) {
        // Nothing to do.
      } else if (calleeIsStatic) {
        _dispatch(target);
      } else if (isNullAware) {
        targetType = _dispatch(target);
      } else {
        targetType = _handleTarget(target, node.methodName.name, callee);
      }
    } else if (target == null && callee!.enclosingElement is ClassElement) {
      targetType = _thisOrSuper(node);
      _checkThisNotNull(targetType, node);
    }
    DecoratedType? expressionType;
    DecoratedType? calleeType;
    if (targetType != null &&
        targetType.type is FunctionType &&
        node.methodName.name == 'call') {
      // If `X` has a function type, then in the expression `X.call()`, the
      // function being called is `X` itself, so the callee type is simply the
      // type of `X`.
      calleeType = targetType;
    } else if (callee != null) {
      calleeType = getOrComputeElementType(node, callee,
          targetType: targetType, targetExpression: target);
      if (callee is PropertyAccessorElement) {
        calleeType = calleeType.returnType;
      }
    }
    if (calleeType == null) {
      // Dynamic dispatch.  The return type is `dynamic`.
      // TODO(paulberry): would it be better to assume a return type of `Never`
      // so that we don't unnecessarily propagate nullabilities everywhere?
      _dispatch(node.argumentList);
      expressionType = _makeNullableDynamicType(node);
    } else {
      expressionType = _handleInvocationArguments(
          node,
          node.argumentList.arguments,
          node.typeArguments,
          node.typeArgumentTypes,
          calleeType,
          null,
          invokeType: node.staticInvokeType);
      // Do any deferred processing for this method invocation.
      var deferredProcessing = _deferredMethodInvocationProcessing.remove(node);
      if (deferredProcessing != null) {
        expressionType = deferredProcessing(expressionType);
      }
      if (isNullAware) {
        expressionType = expressionType!.withNode(
            NullabilityNode.forLUB(targetType!.node, expressionType.node));
      }
      _variables!.recordDecoratedExpressionType(node, expressionType);
    }
    _handleCustomCheckNotNull(node);
    _handleQuiverCheckNotNull(node);
    return expressionType;
  }

  @override
  DecoratedType? visitMixinDeclaration(MixinDeclaration node) {
    visitClassOrMixinOrExtensionDeclaration(node);
    _dispatch(node.implementsClause);
    _dispatch(node.onClause);
    _dispatch(node.typeParameters);
    return null;
  }

  @override
  DecoratedType? visitNamedType(NamedType node) {
    try {
      _typeNameNesting++;
      var typeArguments = node.typeArguments?.arguments;
      var element = node.name.staticElement;
      if (element is TypeAliasElement) {
        var aliasedElement =
            element.aliasedElement as GenericFunctionTypeElement;
        final typedefType = _variables!.decoratedElementType(aliasedElement);
        final typeNameType = _variables!.decoratedTypeAnnotation(source, node);

        Map<TypeParameterElement, DecoratedType> substitutions;
        if (node.typeArguments == null) {
          // TODO(mfairhurst): substitute instantiations to bounds
          substitutions = {};
        } else {
          substitutions =
              Map<TypeParameterElement, DecoratedType>.fromIterables(
                  element.typeParameters,
                  node.typeArguments!.arguments.map(
                      (t) => _variables!.decoratedTypeAnnotation(source, t)));
        }

        final decoratedType = typedefType.substitute(substitutions);
        final origin = TypedefReferenceOrigin(source, node);
        _linkDecoratedTypeParameters(decoratedType, typeNameType, origin,
            isUnion: true);
        _linkDecoratedTypes(
            decoratedType.returnType!, typeNameType.returnType, origin,
            isUnion: true);
      } else if (element is TypeParameterizedElement) {
        if (typeArguments == null) {
          var instantiatedType =
              _variables!.decoratedTypeAnnotation(source, node);
          var origin = InstantiateToBoundsOrigin(source, node);
          for (int i = 0; i < instantiatedType.typeArguments.length; i++) {
            _linkDecoratedTypes(
                instantiatedType.typeArguments[i]!,
                _variables!
                    .decoratedTypeParameterBound(element.typeParameters[i]),
                origin,
                isUnion: false);
          }
        } else {
          for (int i = 0; i < typeArguments.length; i++) {
            DecoratedType? bound;
            bound = _variables!
                .decoratedTypeParameterBound(element.typeParameters[i]);
            assert(bound != null);
            var argumentType =
                _variables!.decoratedTypeAnnotation(source, typeArguments[i]);
            _checkAssignment(
                TypeParameterInstantiationOrigin(source, typeArguments[i]),
                FixReasonTarget.root,
                source: argumentType,
                destination: bound!,
                hard: true);
          }
        }
      }
      node.visitChildren(this);
      // If the type name is followed by a `/*!*/` comment, it is considered to
      // apply to the type and not to the "as" expression.  In order to prevent
      // a future call to _handleNullCheck from interpreting it as applying to
      // the "as" expression, we need to store the `/*!*/` comment in
      // _nullCheckHints.
      var token = node.endToken;
      _nullCheckHints[token] = getPostfixHint(token);
      namedTypeVisited(node); // Note this has been visited to TypeNameTracker.
      return null;
    } finally {
      _typeNameNesting--;
    }
  }

  @override
  DecoratedType? visitNamespaceDirective(NamespaceDirective node) {
    // skip directives, but not their metadata
    _dispatchList(node.metadata);
    return null;
  }

  @override
  DecoratedType? visitNode(AstNode node) {
    for (var child in node.childEntities) {
      if (child is AstNode) {
        _dispatch(child);
      }
    }
    return null;
  }

  @override
  DecoratedType visitNullLiteral(NullLiteral node) {
    _flowAnalysis!.nullLiteral(node);
    var target = NullabilityNodeTarget.text('null literal').withCodeRef(node);
    var decoratedType = DecoratedType.forImplicitType(
        typeProvider, node.staticType, _graph, target);
    _graph.makeNullable(decoratedType.node!, LiteralOrigin(source, node));
    return decoratedType;
  }

  @override
  DecoratedType? visitParenthesizedExpression(ParenthesizedExpression node) {
    var result = _dispatch(node.expression);
    _flowAnalysis!.parenthesizedExpression(node, node.expression);
    return result;
  }

  @override
  DecoratedType? visitPartOfDirective(PartOfDirective node) {
    // skip directives, but not their metadata
    _dispatchList(node.metadata);
    return null;
  }

  @override
  DecoratedType visitPostfixExpression(PostfixExpression node) {
    if (node.operator.type.isIncrementOperator) {
      var operand = node.operand;
      var targetType = _checkExpressionNotNull(operand);
      var callee = node.staticElement;
      DecoratedType writeType;
      if (callee == null) {
        // Dynamic dispatch.  The return type is `dynamic`.
        // TODO(paulberry): would it be better to assume a return type of `Never`
        // so that we don't unnecessarily propagate nullabilities everywhere?
        writeType = _makeNullableDynamicType(node);
      } else {
        var calleeType = getOrComputeElementType(node, callee,
            targetType: targetType, targetExpression: operand);
        writeType = _fixNumericTypes(calleeType.returnType!, node.staticType);
      }
      if (operand is SimpleIdentifier) {
        var element = getWriteOrReadElement(operand);
        if (element is PromotableElement) {
          _flowAnalysis!.write(node, element, writeType, null);
        }
      }
      return targetType;
    }
    _unimplemented(
        node, 'Postfix expression with operator ${node.operator.lexeme}');
  }

  @override
  DecoratedType? visitPrefixedIdentifier(PrefixedIdentifier node) {
    if (node.prefix.staticElement is ImportElement) {
      // TODO(paulberry)
      _unimplemented(node, 'PrefixedIdentifier with a prefix');
    } else {
      return _handlePropertyAccess(
          node, node.prefix, node.identifier, false, false);
    }
  }

  @override
  DecoratedType? visitPrefixExpression(PrefixExpression node) {
    var operand = node.operand;
    var targetType = _checkExpressionNotNull(operand);
    var operatorType = node.operator.type;
    if (operatorType == TokenType.BANG) {
      _flowAnalysis!.logicalNot_end(node, operand);
      return _makeNonNullableBoolType(node);
    } else {
      var callee = node.staticElement;
      var isIncrementOrDecrement = operatorType.isIncrementOperator;
      DecoratedType? staticType;
      if (callee == null) {
        // Dynamic dispatch.  The return type is `dynamic`.
        // TODO(paulberry): would it be better to assume a return type of `Never`
        // so that we don't unnecessarily propagate nullabilities everywhere?
        staticType = _makeNullableDynamicType(node);
      } else {
        var calleeType = getOrComputeElementType(node, callee,
            targetType: targetType, targetExpression: operand);
        if (isIncrementOrDecrement) {
          staticType =
              _fixNumericTypes(calleeType.returnType!, node.staticType);
        } else {
          staticType = _handleInvocationArguments(
              node, [], null, null, calleeType, null);
        }
      }
      if (isIncrementOrDecrement) {
        if (operand is SimpleIdentifier) {
          var element = getWriteOrReadElement(operand);
          if (element is PromotableElement) {
            _flowAnalysis!.write(node, element, staticType!, null);
          }
        }
      }
      return staticType;
    }
  }

  @override
  DecoratedType? visitPropertyAccess(PropertyAccess node) {
    return _handlePropertyAccess(node, node.target, node.propertyName,
        node.isNullAware, node.isCascaded);
  }

  @override
  DecoratedType? visitRedirectingConstructorInvocation(
      RedirectingConstructorInvocation node) {
    var callee = node.staticElement!;
    var calleeType = _variables!.decoratedElementType(callee);
    _handleInvocationArguments(
        node, node.argumentList.arguments, null, null, calleeType, null);
    return null;
  }

  @override
  DecoratedType visitRethrowExpression(RethrowExpression node) {
    _flowAnalysis!.handleExit();
    var target =
        NullabilityNodeTarget.text('rethrow expression').withCodeRef(node);
    var nullabilityNode = NullabilityNode.forInferredType(target);
    _graph.makeNonNullable(nullabilityNode, ThrowOrigin(source, node));
    return DecoratedType(node.staticType, nullabilityNode);
  }

  @override
  DecoratedType? visitReturnStatement(ReturnStatement node) {
    DecoratedType? returnType = _currentFunctionType!.returnType;
    Expression? returnValue = node.expression;
    var functionBody = node.thisOrAncestorOfType<FunctionBody>()!;
    if (functionBody.isGenerator) {
      // Do not connect the return value to the return type.
      return _dispatch(returnValue);
    }
    final isAsync = functionBody.isAsynchronous;
    if (returnValue == null) {
      var target =
          NullabilityNodeTarget.text('implicit null return').withCodeRef(node);
      var implicitNullType = DecoratedType.forImplicitType(
          typeProvider, typeProvider.nullType, _graph, target);
      var origin = ImplicitNullReturnOrigin(source, node);
      _graph.makeNullable(implicitNullType.node!, origin);
      _checkAssignment(origin, FixReasonTarget.root,
          source:
              isAsync ? _futureOf(implicitNullType, node) : implicitNullType,
          destination: returnType!,
          hard: false);
    } else {
      _handleAssignment(returnValue,
          destinationType: returnType, wrapFuture: isAsync);
    }

    _flowAnalysis!.handleExit();
    // Later statements no longer post-dominate the declarations because we
    // exited (or, in parent scopes, conditionally exited).
    // TODO(mfairhurst): don't clear post-dominators beyond the current function.
    _postDominatedLocals.clearEachScope();

    return null;
  }

  @override
  DecoratedType visitSetOrMapLiteral(SetOrMapLiteral node) {
    var setOrMapType = node.staticType as InterfaceType?;
    var typeArguments = node.typeArguments?.arguments;

    if (node.isSet) {
      final previousLiteralType = _currentLiteralElementType;
      try {
        if (typeArguments == null) {
          assert(setOrMapType!.typeArguments.length == 1);
          var target =
              NullabilityNodeTarget.text('set element type').withCodeRef(node);
          var elementType = DecoratedType.forImplicitType(
              typeProvider, setOrMapType!.typeArguments[0], _graph, target);
          instrumentation?.implicitTypeArguments(source, node, [elementType]);
          _currentLiteralElementType = elementType;
        } else {
          assert(typeArguments.length == 1);
          _dispatch(node.typeArguments);
          _currentLiteralElementType =
              _variables!.decoratedTypeAnnotation(source, typeArguments[0]);
        }
        node.elements.forEach(_handleCollectionElement);
        return _makeNonNullLiteralType(node,
            typeArguments: [_currentLiteralElementType]);
      } finally {
        _currentLiteralElementType = previousLiteralType;
      }
    } else {
      assert(node.isMap);

      final previousKeyType = _currentMapKeyType;
      final previousValueType = _currentMapValueType;
      try {
        if (typeArguments == null) {
          assert(setOrMapType!.typeArguments.length == 2);
          var targetKey =
              NullabilityNodeTarget.text('map key type').withCodeRef(node);
          var keyType = DecoratedType.forImplicitType(
              typeProvider, setOrMapType!.typeArguments[0], _graph, targetKey);
          _currentMapKeyType = keyType;
          var targetValue =
              NullabilityNodeTarget.text('map value type').withCodeRef(node);
          var valueType = DecoratedType.forImplicitType(
              typeProvider, setOrMapType.typeArguments[1], _graph, targetValue);
          _currentMapValueType = valueType;
          instrumentation
              ?.implicitTypeArguments(source, node, [keyType, valueType]);
        } else {
          assert(typeArguments.length == 2);
          _dispatch(node.typeArguments);
          _currentMapKeyType =
              _variables!.decoratedTypeAnnotation(source, typeArguments[0]);
          _currentMapValueType =
              _variables!.decoratedTypeAnnotation(source, typeArguments[1]);
        }

        node.elements.forEach(_handleCollectionElement);
        return _makeNonNullLiteralType(node,
            typeArguments: [_currentMapKeyType, _currentMapValueType]);
      } finally {
        _currentMapKeyType = previousKeyType;
        _currentMapValueType = previousValueType;
      }
    }
  }

  @override
  DecoratedType? visitSimpleIdentifier(SimpleIdentifier node) {
    DecoratedType? targetType;
    DecoratedType? result;
    var staticElement = _favorFieldFormalElements(getWriteOrReadElement(node));
    if (staticElement is PromotableElement) {
      if (!node.inDeclarationContext()) {
        var promotedType = _flowAnalysis!.variableRead(node, staticElement);
        if (promotedType != null) return promotedType;
      }
      var type = getOrComputeElementType(node, staticElement);
      if (!node.inDeclarationContext() &&
          node.inGetterContext() &&
          !_lateHintedLocals.contains(staticElement) &&
          !_flowAnalysis!.isAssigned(staticElement)) {
        _graph.makeNullable(type.node!, UninitializedReadOrigin(source, node));
      }
      result = type;
    } else if (staticElement is FunctionElement ||
        staticElement is MethodElement ||
        staticElement is ConstructorElement) {
      if (staticElement!.enclosingElement is ClassElement) {
        targetType = _thisOrSuper(node);
      }
      result =
          getOrComputeElementType(node, staticElement, targetType: targetType);
    } else if (staticElement is PropertyAccessorElement) {
      if (staticElement.enclosingElement is ClassElement) {
        targetType = _thisOrSuper(node);
      }
      var elementType =
          getOrComputeElementType(node, staticElement, targetType: targetType);
      result = staticElement.isGetter
          ? elementType.returnType
          : elementType.positionalParameters![0];
    } else if (staticElement is TypeDefiningElement) {
      result = _makeNonNullLiteralType(node);
    } else if (staticElement is ExtensionElement) {
      result = _makeNonNullLiteralType(node);
    } else if (staticElement == null) {
      assert(node.toString() == 'void', "${node.toString()} != 'void'");
      result = _makeNullableVoidType(node);
    } else if (staticElement.enclosingElement is ClassElement &&
        (staticElement.enclosingElement as ClassElement).isEnum) {
      result = getOrComputeElementType(node, staticElement);
    } else {
      // TODO(paulberry)
      _unimplemented(node,
          'Simple identifier with a static element of type ${staticElement.runtimeType}');
    }
    if (targetType != null) {
      _checkThisNotNull(targetType, node);
    }
    return result;
  }

  @override
  DecoratedType? visitSpreadElement(SpreadElement node) {
    final spreadType = node.expression.staticType!;
    DecoratedType? spreadTypeDecorated;
    var target =
        NullabilityNodeTarget.text('spread element type').withCodeRef(node);
    if (_typeSystem.isSubtypeOf(spreadType, typeProvider.mapObjectObjectType)) {
      assert(_currentMapKeyType != null && _currentMapValueType != null);
      final expectedType = typeProvider.mapType(
          _currentMapKeyType!.type!, _currentMapValueType!.type!);
      final expectedDecoratedType = DecoratedType.forImplicitType(
          typeProvider, expectedType, _graph, target,
          typeArguments: [_currentMapKeyType, _currentMapValueType]);

      spreadTypeDecorated = _handleAssignment(node.expression,
          destinationType: expectedDecoratedType);
    } else if (_typeSystem.isSubtypeOf(
        spreadType, typeProvider.iterableDynamicType)) {
      assert(_currentLiteralElementType != null);
      final expectedType =
          typeProvider.iterableType(_currentLiteralElementType!.type!);
      final expectedDecoratedType = DecoratedType.forImplicitType(
          typeProvider, expectedType, _graph, target,
          typeArguments: [_currentLiteralElementType]);

      spreadTypeDecorated = _handleAssignment(node.expression,
          destinationType: expectedDecoratedType);
    } else {
      // Downcast. We can't assume nullability here, so do nothing.
    }

    if (!node.isNullAware) {
      _checkExpressionNotNull(node.expression, sourceType: spreadTypeDecorated);
    }

    return null;
  }

  @override
  DecoratedType visitStringLiteral(StringLiteral node) {
    node.visitChildren(this);
    return _makeNonNullLiteralType(node);
  }

  @override
  DecoratedType? visitSuperConstructorInvocation(
      SuperConstructorInvocation node) {
    var callee = node.staticElement!;
    var target = NullabilityNodeTarget.text('super constructor invocation')
        .withCodeRef(node);
    var nullabilityNode = NullabilityNode.forInferredType(target);
    var class_ = node.thisOrAncestorOfType<ClassDeclaration>()!;
    var decoratedSupertype = _decoratedClassHierarchy!.getDecoratedSupertype(
        class_.declaredElement!, callee.enclosingElement);
    var typeArguments = decoratedSupertype.typeArguments;
    Iterable<DartType?> typeArgumentTypes;
    typeArgumentTypes = typeArguments.map((t) => t!.type);
    var createdType = DecoratedType(callee.returnType, nullabilityNode,
        typeArguments: typeArguments);
    var calleeType =
        getOrComputeElementType(node, callee, targetType: createdType);
    var constructorTypeParameters = callee.enclosingElement.typeParameters;

    _handleInvocationArguments(
        node,
        node.argumentList.arguments,
        null /*typeArguments*/,
        typeArgumentTypes,
        calleeType,
        constructorTypeParameters);
    return null;
  }

  @override
  DecoratedType? visitSuperExpression(SuperExpression node) {
    return _thisOrSuper(node);
  }

  @override
  DecoratedType? visitSwitchStatement(SwitchStatement node) {
    _dispatch(node.expression);
    _flowAnalysis!.switchStatement_expressionEnd(node);
    var hasDefault = false;
    for (var member in node.members) {
      _postDominatedLocals.doScoped(action: () {
        var hasLabel = member.labels.isNotEmpty;
        _flowAnalysis!.switchStatement_beginCase(hasLabel, node);
        if (member is SwitchCase) {
          _dispatch(member.expression);
        } else {
          hasDefault = true;
        }
        _dispatchList(member.statements);
      });
    }
    _flowAnalysis!.switchStatement_end(hasDefault);
    return null;
  }

  @override
  DecoratedType visitSymbolLiteral(SymbolLiteral node) {
    return _makeNonNullLiteralType(node);
  }

  @override
  DecoratedType? visitThisExpression(ThisExpression node) {
    return _thisOrSuper(node);
  }

  @override
  DecoratedType visitThrowExpression(ThrowExpression node) {
    _dispatch(node.expression);
    // TODO(paulberry): do we need to check the expression type?  I think not.
    _flowAnalysis!.handleExit();
    var target =
        NullabilityNodeTarget.text('throw expression').withCodeRef(node);
    var nullabilityNode = NullabilityNode.forInferredType(target);
    _graph.makeNonNullable(nullabilityNode, ThrowOrigin(source, node));
    return DecoratedType(node.staticType, nullabilityNode);
  }

  @override
  DecoratedType? visitTryStatement(TryStatement node) {
    var finallyBlock = node.finallyBlock;
    if (finallyBlock != null) {
      _flowAnalysis!.tryFinallyStatement_bodyBegin();
    }
    var catchClauses = node.catchClauses;
    if (catchClauses.isNotEmpty) {
      _flowAnalysis!.tryCatchStatement_bodyBegin();
    }
    var body = node.body;
    _dispatch(body);
    if (catchClauses.isNotEmpty) {
      _flowAnalysis!.tryCatchStatement_bodyEnd(body);
      _dispatchList(catchClauses);
      _flowAnalysis!.tryCatchStatement_end();
    }
    if (finallyBlock != null) {
      _flowAnalysis!.tryFinallyStatement_finallyBegin(
          catchClauses.isNotEmpty ? node : body);
      _dispatch(finallyBlock);
      _flowAnalysis!.tryFinallyStatement_end();
    }
    return null;
  }

  @override
  DecoratedType? visitVariableDeclarationList(VariableDeclarationList node) {
    var parent = node.parent;
    bool isTopLevel =
        parent is FieldDeclaration || parent is TopLevelVariableDeclaration;
    _dispatchList(node.metadata);
    _dispatch(node.type);
    for (var variable in node.variables) {
      _dispatchList(variable.metadata);
      var initializer = variable.initializer;
      var declaredElement = variable.declaredElement!;
      if (isTopLevel) {
        assert(_flowAnalysis == null);
        _createFlowAnalysis(variable, null);
      } else {
        assert(_flowAnalysis != null);
        if (declaredElement is PromotableElement &&
            _variables!.getLateHint(source, node) != null) {
          _lateHintedLocals.add(declaredElement);
        }
      }
      var type = _variables!.decoratedElementType(declaredElement);
      var enclosingElement = declaredElement.enclosingElement;
      if (!declaredElement.isStatic && enclosingElement is ClassElement) {
        var overriddenElements = _inheritanceManager.getOverridden2(
            enclosingElement,
            Name(enclosingElement.library.source.uri, declaredElement.name));
        for (var overriddenElement
            in overriddenElements ?? <ExecutableElement>[]) {
          _handleFieldOverriddenDeclaration(
              variable, type, enclosingElement, overriddenElement);
        }
        if (!declaredElement.isFinal) {
          var overriddenElements = _inheritanceManager.getOverridden2(
              enclosingElement,
              Name(enclosingElement.library.source.uri,
                  '${declaredElement.name}='));
          for (var overriddenElement
              in overriddenElements ?? <ExecutableElement>[]) {
            _handleFieldOverriddenDeclaration(
                variable, type, enclosingElement, overriddenElement);
          }
        }
      }
      try {
        if (declaredElement is PromotableElement) {
          _flowAnalysis!.declare(declaredElement, initializer != null);
        }
        if (initializer == null) {
          // For top level variables and static fields, we have to generate an
          // implicit assignment of `null`.  For instance fields, this is done
          // when processing constructors.  For local variables, this is done
          // when processing variable reads (only if flow analysis indicates
          // the variable isn't definitely assigned).
          if (isTopLevel &&
              _variables!.getLateHint(source, node) == null &&
              !(declaredElement is FieldElement && !declaredElement.isStatic)) {
            _graph.makeNullable(
                type.node!, ImplicitNullInitializerOrigin(source, node));
          }
        } else {
          _handleAssignment(initializer, destinationType: type);
        }
        if (isTopLevel) {
          _flowAnalysis!.finish();
        }
      } finally {
        if (isTopLevel) {
          _flowAnalysis = null;
          _assignedVariables = null;
        }
      }
    }

    // Track post-dominators, except we cannot make hard edges to multi
    // declarations. Consider:
    //
    // int? x = null, y = 0;
    // y.toDouble();
    //
    // We cannot make a hard edge from y to never in this case.
    if (node.variables.length == 1) {
      _postDominatedLocals.add(node.variables.single.declaredElement!);
    }

    return null;
  }

  @override
  DecoratedType? visitWhileStatement(WhileStatement node) {
    // Note: we do not create guards. A null check here is *very* unlikely to be
    // unnecessary after analysis.
    _flowAnalysis!.whileStatement_conditionBegin(node);
    _checkExpressionNotNull(node.condition);
    _flowAnalysis!.whileStatement_bodyBegin(node, node.condition);
    _postDominatedLocals.doScoped(action: () => _dispatch(node.body));
    _flowAnalysis!.whileStatement_end();
    return null;
  }

  void _addParametersToFlowAnalysis(FormalParameterList? parameters) {
    if (parameters != null) {
      for (var parameter in parameters.parameters) {
        _flowAnalysis!.declare(parameter.declaredElement!, true);
      }
    }
  }

  /// Visits [expression] and generates the appropriate edge to assert that its
  /// value is non-null.
  ///
  /// Returns the decorated type of [expression].
  DecoratedType _checkExpressionNotNull(Expression expression,
      {DecoratedType? sourceType}) {
    if (_isPrefix(expression)) {
      throw ArgumentError('cannot check non-nullability of a prefix');
    }
    sourceType ??= _dispatch(expression);
    if (sourceType == null) {
      throw StateError('No type computed for ${expression.runtimeType} '
          '(${expression.toSource()}) offset=${expression.offset}');
    }
    var origin = _makeEdgeOrigin(sourceType, expression);
    var hard = _shouldUseHardEdge(expression);
    var edge = _graph.makeNonNullable(sourceType.node, origin,
        hard: hard, guards: _guards);
    if (origin is ExpressionChecksOrigin) {
      origin.checks.edges[FixReasonTarget.root] = edge;
    }
    return sourceType;
  }

  /// Generates the appropriate edge to assert that the value of `this` is
  /// non-null.
  void _checkThisNotNull(DecoratedType? thisType, AstNode node) {
    // `this` can only be `null` in extensions, so if we're not in an extension,
    // there's nothing to do.
    if (_currentExtendedType == null) return;
    var origin = ImplicitThisOrigin(source, node);
    var hard = _postDominatedLocals.isInScope(_extensionThis);
    _graph.makeNonNullable(thisType!.node, origin, hard: hard, guards: _guards);
  }

  /// Computes the map to be stored in [_currentFieldFormals] while visiting the
  /// constructor having the given [constructorElement].
  Map<PropertyAccessorElement, FieldFormalParameterElement>
      _computeFieldFormalMap(ConstructorElement constructorElement) {
    var result = <PropertyAccessorElement, FieldFormalParameterElement>{};
    for (var parameter in constructorElement.parameters) {
      if (parameter is FieldFormalParameterElement) {
        var getter = parameter.field?.getter;
        if (getter != null) {
          result[getter] = parameter;
        }
      }
    }
    return result;
  }

  @override
  void _connect(NullabilityNode? source, NullabilityNode? destination,
      EdgeOrigin origin, FixReasonTarget? edgeTarget,
      {bool hard = false, bool checkable = true}) {
    var edge = _graph.connect(source, destination!, origin,
        hard: hard, checkable: checkable, guards: _guards);
    if (origin is ExpressionChecksOrigin) {
      origin.checks.edges[edgeTarget] = edge;
    }
  }

  void _createFlowAnalysis(Declaration node, FormalParameterList? parameters) {
    assert(_flowAnalysis == null);
    assert(_assignedVariables == null);
    _assignedVariables =
        FlowAnalysisHelper.computeAssignedVariables(node, parameters);
    // Note: we are using flow analysis to help us track true nullabilities;
    // it's not necessary to replicate old bugs.  So we pass `true` for
    // `respectImplicitlyTypedVarInitializers`.
    _flowAnalysis = FlowAnalysis<AstNode, Statement, Expression,
            PromotableElement, DecoratedType>(
        DecoratedTypeOperations(_typeSystem, _variables, _graph),
        _assignedVariables!,
        respectImplicitlyTypedVarInitializers: true);
    if (parameters != null) {
      for (var parameter in parameters.parameters) {
        _flowAnalysis!.declare(parameter.declaredElement!, true);
      }
    }
  }

  /// Creates a type that can be used to check that an expression's value is
  /// non-nullable.
  DecoratedType _createNonNullableType(Expression expression) {
    var target =
        NullabilityNodeTarget.text('expression type').withCodeRef(expression);
    // Note: it's not necessary for the type to precisely match the type of the
    // expression, since all we are going to do is cause a single graph edge to
    // be built; it is sufficient to pass in any decorated type whose node is
    // non-nullable.  So we use `Object`.
    var nullabilityNode = NullabilityNode.forInferredType(target);
    _graph.makeNonNullableUnion(
        nullabilityNode, NonNullableUsageOrigin(source, expression));
    return DecoratedType(typeProvider.objectType, nullabilityNode);
  }

  DecoratedType _decorateUpperOrLowerBound(AstNode astNode, DartType? type,
      DecoratedType left, DecoratedType right, bool isLUB,
      {NullabilityNode? node}) {
    var leftType = left.type;
    var rightType = right.type;
    if (leftType is TypeParameterType && leftType != type) {
      // We are "unwrapping" a type parameter type to its bound.
      final typeParam = leftType.element;
      return _decorateUpperOrLowerBound(
          astNode,
          type,
          left.substitute(
              {typeParam: _variables!.decoratedTypeParameterBound(typeParam)}),
          right,
          isLUB,
          node: node);
    }
    if (rightType is TypeParameterType && rightType != type) {
      // We are "unwrapping" a type parameter type to its bound.
      final typeParam = rightType.element;
      return _decorateUpperOrLowerBound(
          astNode,
          type,
          left,
          right.substitute(
              {typeParam: _variables!.decoratedTypeParameterBound(typeParam)}),
          isLUB,
          node: node);
    }

    node ??= isLUB
        ? NullabilityNode.forLUB(left.node, right.node)
        : _nullabilityNodeForGLB(astNode, left.node!, right.node!);

    if (type!.isDynamic || type.isVoid) {
      return DecoratedType(type, node);
    } else if (leftType!.isBottom) {
      return right.withNode(node);
    } else if (rightType!.isBottom) {
      return left.withNode(node);
    } else if (type is InterfaceType) {
      if (type.typeArguments.isEmpty) {
        return DecoratedType(type, node);
      } else {
        if (leftType.isDartCoreNull) {
          assert(isLUB, "shouldn't be possible to get C<T> from GLB(null, S)");
          return DecoratedType(type, node, typeArguments: right.typeArguments);
        } else if (rightType.isDartCoreNull) {
          assert(isLUB, "shouldn't be possible to get C<T> from GLB(S, null)");
          return DecoratedType(type, node, typeArguments: left.typeArguments);
        } else if (leftType is InterfaceType && rightType is InterfaceType) {
          List<DecoratedType?> leftTypeArguments;
          List<DecoratedType?> rightTypeArguments;
          if (isLUB) {
            leftTypeArguments = _decoratedClassHierarchy!
                .asInstanceOf(left, type.element)
                .typeArguments;
            rightTypeArguments = _decoratedClassHierarchy!
                .asInstanceOf(right, type.element)
                .typeArguments;
          } else {
            if (leftType.element != type.element ||
                rightType.element != type.element) {
              _unimplemented(astNode, 'GLB with substitution');
            }
            leftTypeArguments = left.typeArguments;
            rightTypeArguments = right.typeArguments;
          }
          List<DecoratedType> newTypeArguments = [];
          for (int i = 0; i < type.typeArguments.length; i++) {
            newTypeArguments.add(_decorateUpperOrLowerBound(
                astNode,
                type.typeArguments[i],
                leftTypeArguments[i]!,
                rightTypeArguments[i]!,
                isLUB));
          }
          return DecoratedType(type, node, typeArguments: newTypeArguments);
        } else {
          _unimplemented(
              astNode,
              'LUB/GLB with unexpected types: ${leftType.runtimeType}/'
              '${rightType.runtimeType}');
        }
      }
    } else if (type is FunctionType) {
      var leftType = left.type!;
      var rightType = right.type;
      if (leftType.isDartCoreNull) {
        assert(
            isLUB, "shouldn't be possible to get a function from GLB(null, S)");
        return DecoratedType(type, node,
            returnType: right.returnType,
            positionalParameters: right.positionalParameters,
            namedParameters: right.namedParameters);
      } else if (rightType!.isDartCoreNull) {
        assert(
            isLUB, "shouldn't be possible to get a function from GLB(S, null)");
        return DecoratedType(type, node,
            returnType: left.returnType,
            positionalParameters: left.positionalParameters,
            namedParameters: left.namedParameters);
      }
      if (leftType is FunctionType && rightType is FunctionType) {
        var returnType = _decorateUpperOrLowerBound(astNode, type.returnType,
            left.returnType!, right.returnType!, isLUB);
        List<DecoratedType> positionalParameters = [];
        Map<String, DecoratedType> namedParameters = {};
        int positionalParameterCount = 0;
        for (var parameter in type.parameters) {
          DecoratedType? leftParameterType;
          DecoratedType? rightParameterType;
          if (parameter.isNamed) {
            leftParameterType = left.namedParameters![parameter.name];
            rightParameterType = right.namedParameters![parameter.name];
          } else {
            leftParameterType =
                left.positionalParameters![positionalParameterCount];
            rightParameterType =
                right.positionalParameters![positionalParameterCount];
            positionalParameterCount++;
          }
          var decoratedParameterType = _decorateUpperOrLowerBound(astNode,
              parameter.type, leftParameterType!, rightParameterType!, !isLUB);
          if (parameter.isNamed) {
            namedParameters[parameter.name] = decoratedParameterType;
          } else {
            positionalParameters.add(decoratedParameterType);
          }
        }
        return DecoratedType(type, node,
            returnType: returnType,
            positionalParameters: positionalParameters,
            namedParameters: namedParameters);
      } else {
        _unimplemented(
            astNode,
            'LUB/GLB with unexpected types: ${leftType.runtimeType}/'
            '${rightType.runtimeType}');
      }
    } else if (type is TypeParameterType) {
      var leftType = left.type!;
      var rightType = right.type;
      if (leftType.isDartCoreNull || rightType!.isDartCoreNull) {
        assert(isLUB, "shouldn't be possible to get T from GLB(null, S)");
        return DecoratedType(type, node);
      }

      assert(leftType.element == type.element &&
          rightType.element == type.element);
      return DecoratedType(type, node);
    }
    _unimplemented(astNode, '_decorateUpperOrLowerBound');
  }

  DecoratedType? _dispatch(AstNode? node, {bool skipNullCheckHint = false}) {
    try {
      var type = node?.accept(this);
      if (!skipNullCheckHint && node is Expression) {
        type = _handleNullCheckHint(node, type);
      }
      return type;
    } catch (exception, stackTrace) {
      if (listener != null) {
        listener!.reportException(source, node, exception, stackTrace);
        return null;
      } else {
        rethrow;
      }
    }
  }

  void _dispatchList(NodeList? nodeList) {
    if (nodeList == null) return;
    for (var node in nodeList) {
      _dispatch(node);
    }
  }

  /// If the innermost enclosing executable is a constructor with field formal
  /// parameters, and [staticElement] refers to the getter associated with one
  /// of those fields, returns the corresponding field formal parameter element.
  /// Otherwise returns [staticElement] unchanged.
  ///
  /// This allows us to treat null checks on the field as though they were null
  /// checks on the field formal parameter, which is not strictly correct, but
  /// tends to produce migrations that are more in line with user intent.
  Element? _favorFieldFormalElements(Element? staticElement) {
    if (staticElement is PropertyAccessorElement) {
      var fieldFormal = _currentFieldFormals[staticElement];
      if (fieldFormal != null) {
        return fieldFormal;
      }
    }
    return staticElement;
  }

  DecoratedType _fixNumericTypes(
      DecoratedType decoratedType, DartType? undecoratedType) {
    if (decoratedType.type!.isDartCoreNum && undecoratedType!.isDartCoreInt) {
      // In a few cases the type computed by normal method lookup is `num`,
      // but special rules kick in to cause the type to be `int` instead.  If
      // that is the case, we need to fix up the decorated type.
      return DecoratedType(undecoratedType, decoratedType.node);
    } else {
      return decoratedType;
    }
  }

  DecoratedType _futureOf(DecoratedType type, AstNode node) =>
      DecoratedType.forImplicitType(
          typeProvider,
          typeProvider.futureType(type.type!),
          _graph,
          NullabilityNodeTarget.text('implicit future').withCodeRef(node),
          typeArguments: [type]);

  @override
  DecoratedType? _getCallMethodType(DecoratedType type) {
    var typeType = type.type;
    if (typeType is InterfaceType) {
      var callMethod = typeType.lookUpMethod2('call', _library);
      if (callMethod != null) {
        return _variables!
            .decoratedElementType(callMethod.declaration)
            .substitute(type.asSubstitution);
      }
    }
    return null;
  }

  @override
  DecoratedType? _getTypeParameterTypeBound(DecoratedType type) {
    // TODO(paulberry): once we've wired up flow analysis, return promoted
    // bounds if applicable.
    return _variables!
        .decoratedTypeParameterBound((type.type as TypeParameterType).element);
  }

  /// Creates the necessary constraint(s) for an assignment of the given
  /// [expression] to a destination whose type is [destinationType].
  ///
  /// Optionally, the caller may supply an [assignmentExpression] instead of
  /// [destinationType].  In this case, then the type comes from visiting the
  /// LHS of the assignment expression.  If the LHS of the assignment expression
  /// refers to a local variable, we mark it as assigned in flow analysis at the
  /// proper time.
  ///
  /// Set [wrapFuture] to true to handle assigning Future<flatten(T)> to R.
  DecoratedType? _handleAssignment(Expression? expression,
      {DecoratedType? destinationType,
      AssignmentExpression? assignmentExpression,
      AssignmentExpression? compoundOperatorInfo,
      AssignmentExpression? questionAssignNode,
      bool fromDefaultValue = false,
      bool wrapFuture = false,
      bool sourceIsSetupCall = false}) {
    assert(
        (assignmentExpression == null) != (destinationType == null),
        'Either assignmentExpression or destinationType should be supplied, '
        'but not both');
    PromotableElement? destinationLocalVariable;
    if (destinationType == null) {
      var destinationExpression = assignmentExpression!.leftHandSide;
      if (destinationExpression is SimpleIdentifier) {
        var element = getWriteOrReadElement(destinationExpression);
        if (element is PromotableElement) {
          destinationLocalVariable = element;
        }
      }
      if (destinationLocalVariable != null) {
        _dispatch(destinationExpression);
        destinationType = getOrComputeElementType(
            destinationExpression, destinationLocalVariable);
      } else {
        destinationType = _dispatch(destinationExpression);
      }
    }

    if (questionAssignNode != null) {
      _guards.add(destinationType!.node);
      _flowAnalysis!.ifNullExpression_rightBegin(
          questionAssignNode.leftHandSide, destinationType);
    }
    DecoratedType? sourceType;
    try {
      sourceType = _dispatch(expression);
      if (wrapFuture) {
        sourceType = _wrapFuture(sourceType!, expression);
      }
      if (sourceType == null) {
        throw StateError('No type computed for ${expression.runtimeType} '
            '(${expression!.toSource()}) offset=${expression.offset}');
      }
      EdgeOrigin edgeOrigin = _makeEdgeOrigin(sourceType, expression,
          isSetupAssignment: sourceIsSetupCall);
      if (compoundOperatorInfo != null) {
        var compoundOperatorMethod = compoundOperatorInfo.staticElement;
        if (compoundOperatorMethod != null) {
          _checkAssignment(
              CompoundAssignmentOrigin(source, compoundOperatorInfo),
              FixReasonTarget.root,
              source: destinationType!,
              destination: _createNonNullableType(compoundOperatorInfo),
              hard: _shouldUseHardEdge(assignmentExpression!.leftHandSide));
          DecoratedType compoundOperatorType = getOrComputeElementType(
              compoundOperatorInfo, compoundOperatorMethod,
              targetType: destinationType,
              targetExpression: compoundOperatorInfo.leftHandSide);
          assert(compoundOperatorType.positionalParameters!.isNotEmpty);
          _checkAssignment(edgeOrigin, FixReasonTarget.root,
              source: sourceType,
              destination: compoundOperatorType.positionalParameters![0]!,
              hard: _shouldUseHardEdge(expression!),
              sourceIsFunctionLiteral: expression is FunctionExpression);
          sourceType = _fixNumericTypes(compoundOperatorType.returnType!,
              compoundOperatorInfo.staticType);
          _checkAssignment(
              CompoundAssignmentOrigin(source, compoundOperatorInfo),
              FixReasonTarget.root,
              source: sourceType,
              destination: destinationType,
              hard: false);
        } else {
          sourceType = _makeNullableDynamicType(compoundOperatorInfo);
        }
      } else {
        if (_tryTransformOrElse(expression, sourceType) ||
            _tryTransformWhere(
                expression, edgeOrigin, sourceType, destinationType!)) {
          // Nothing further to do.
        } else {
          var hard = _shouldUseHardEdge(expression!,
              isConditionallyExecuted: questionAssignNode != null);
          _checkAssignment(edgeOrigin, FixReasonTarget.root,
              source: sourceType,
              destination: destinationType,
              hard: hard,
              sourceIsFunctionLiteral: expression is FunctionExpression);
        }
      }
      if (destinationLocalVariable != null) {
        _flowAnalysis!.write(assignmentExpression!, destinationLocalVariable,
            sourceType, compoundOperatorInfo == null ? expression : null);
      }
      if (questionAssignNode != null) {
        _flowAnalysis!.ifNullExpression_end();
        // a ??= b is only nullable if both a and b are nullable.
        sourceType = destinationType!.withNode(_nullabilityNodeForGLB(
            questionAssignNode, sourceType.node!, destinationType.node!));
        _variables!
            .recordDecoratedExpressionType(questionAssignNode, sourceType);
      }
    } finally {
      if (questionAssignNode != null) {
        _guards.removeLast();
      }
    }
    if (assignmentExpression != null) {
      var element = _referencedElement(assignmentExpression.leftHandSide);
      if (element != null) {
        _postDominatedLocals.removeFromAllScopes(element);
        _elementsWrittenToInLocalFunction?.add(element);
      }
    }
    return sourceType;
  }

  DecoratedType? _handleCollectionElement(CollectionElement? element) {
    if (element is Expression) {
      assert(_currentLiteralElementType != null);
      return _handleAssignment(element,
          destinationType: _currentLiteralElementType);
    } else {
      return _dispatch(element);
    }
  }

  void _handleConstructorRedirection(
      FormalParameterList parameters, ConstructorName redirectedConstructor) {
    var callee = redirectedConstructor.staticElement!.declaration;
    var redirectedClass = callee.enclosingElement;
    var calleeType = _variables!.decoratedElementType(callee);
    var typeArguments = redirectedConstructor.type.typeArguments;
    var typeArgumentTypes =
        typeArguments?.arguments.map((t) => t.type).toList();
    _handleInvocationArguments(
        redirectedConstructor,
        parameters.parameters,
        typeArguments,
        typeArgumentTypes,
        calleeType,
        redirectedClass.typeParameters);
  }

  void _handleCustomCheckNotNull(MethodInvocation node) {
    var callee = node.methodName.staticElement;
    if (node.argumentList.arguments.isNotEmpty &&
        callee is ExecutableElement &&
        callee.isStatic) {
      var enclosingElement = callee.enclosingElement;
      if (enclosingElement is ClassElement) {
        if (callee.name == 'checkNotNull' &&
                enclosingElement.name == 'ArgumentError' &&
                callee.library.isDartCore ||
            callee.name == 'checkNotNull' &&
                enclosingElement.name == 'BuiltValueNullFieldError' &&
                callee.library.source.uri.toString() ==
                    'package:built_value/built_value.dart') {
          var argument = node.argumentList.arguments.first;
          if (argument is SimpleIdentifier && _isReferenceInScope(argument)) {
            var argumentType = _variables!.decoratedElementType(
                _favorFieldFormalElements(getWriteOrReadElement(argument))!);
            _graph.makeNonNullable(argumentType.node,
                ArgumentErrorCheckNotNullOrigin(source, argument));
          }
        }
      }
    }
  }

  void _handleExecutableDeclaration(
      Declaration node,
      ExecutableElement declaredElement,
      NodeList<Annotation> metadata,
      TypeAnnotation? returnType,
      FormalParameterList? parameters,
      NodeList<ConstructorInitializer>? initializers,
      FunctionBody body,
      ConstructorName? redirectedConstructor) {
    assert(_currentFunctionType == null);
    assert(_currentFieldFormals.isEmpty);
    _dispatchList(metadata);
    _dispatch(returnType);
    _createFlowAnalysis(node, parameters);
    _dispatch(parameters);
    _currentFunctionType = _variables!.decoratedElementType(declaredElement);
    _currentFieldFormals = declaredElement is ConstructorElement
        ? _computeFieldFormalMap(declaredElement)
        : const {};
    _addParametersToFlowAnalysis(parameters);
    // Push a scope of post-dominated declarations on the stack.
    _postDominatedLocals.pushScope(elements: declaredElement.parameters);
    if (declaredElement.enclosingElement is ExtensionElement) {
      _postDominatedLocals.add(_extensionThis);
    }
    try {
      _dispatchList(initializers);
      if (declaredElement is ConstructorElement &&
          !declaredElement.isFactory &&
          declaredElement.redirectedConstructor == null) {
        _handleUninitializedFields(node, _fieldsNotInitializedByConstructor!);
      }
      _dispatch(body);
      if (redirectedConstructor != null) {
        _handleConstructorRedirection(parameters!, redirectedConstructor);
      }
      if (declaredElement is! ConstructorElement) {
        var enclosingElement = declaredElement.enclosingElement;
        if (enclosingElement is ClassElement) {
          var overriddenElements = _inheritanceManager.getOverridden2(
              enclosingElement,
              Name(enclosingElement.library.source.uri, declaredElement.name));
          for (var overriddenElement
              in overriddenElements ?? <ExecutableElement>[]) {
            _handleExecutableOverriddenDeclaration(node, returnType, parameters,
                enclosingElement, overriddenElement);
          }
          if (declaredElement is PropertyAccessorElement) {
            if (declaredElement.isGetter) {
              var setters = [declaredElement.correspondingSetter];
              if (setters[0] == null && !declaredElement.isStatic) {
                // No corresponding setter in this class; look for inherited
                // setters.
                var getterName = declaredElement.name;
                var setterName = '$getterName=';
                var inheritedMembers = _inheritanceManager.getOverridden2(
                    enclosingElement,
                    Name(enclosingElement.library.source.uri, setterName));
                if (inheritedMembers != null) {
                  setters = [
                    for (var setter in inheritedMembers)
                      if (setter is PropertyAccessorElement) setter
                  ];
                }
              }
              for (var setter in setters) {
                if (setter != null) {
                  _handleGetterSetterCorrespondence(
                      node,
                      declaredElement.isStatic ? null : enclosingElement,
                      declaredElement,
                      setter.declaration);
                }
              }
            } else {
              assert(declaredElement.isSetter);
              assert(declaredElement.name.endsWith('='));
              var getters = [declaredElement.correspondingGetter];
              if (getters[0] == null && !declaredElement.isStatic) {
                // No corresponding getter in this class; look for inherited
                // getters.
                var setterName = declaredElement.name;
                var getterName = setterName.substring(0, setterName.length - 1);
                var inheritedMembers = _inheritanceManager.getOverridden2(
                    enclosingElement,
                    Name(enclosingElement.library.source.uri, getterName));
                if (inheritedMembers != null) {
                  getters = [
                    for (var getter in inheritedMembers)
                      if (getter is PropertyAccessorElement) getter
                  ];
                }
              }
              for (var getter in getters) {
                if (getter != null) {
                  _handleGetterSetterCorrespondence(
                      node,
                      declaredElement.isStatic ? null : enclosingElement,
                      getter.declaration,
                      declaredElement);
                }
              }
            }
          }
        }
      }
      _flowAnalysis!.finish();
    } finally {
      _flowAnalysis = null;
      _assignedVariables = null;
      _currentFunctionType = null;
      _currentFieldFormals = const {};
      _postDominatedLocals.popScope();
    }
  }

  void _handleExecutableOverriddenDeclaration(
      Declaration node,
      TypeAnnotation? returnType,
      FormalParameterList? parameters,
      ClassElement classElement,
      Element overriddenElement) {
    overriddenElement = overriddenElement.declaration!;
    var overriddenClass = overriddenElement.enclosingElement as ClassElement;
    var decoratedSupertype = _decoratedClassHierarchy!
        .getDecoratedSupertype(classElement, overriddenClass);
    var substitution = decoratedSupertype.asSubstitution;
    if (overriddenElement is PropertyAccessorElement &&
        overriddenElement.isSynthetic) {
      assert(node is MethodDeclaration);
      var method = node as MethodDeclaration;
      var decoratedOverriddenField =
          _variables!.decoratedElementType(overriddenElement.variable);
      var overriddenFieldType =
          decoratedOverriddenField.substitute(substitution);
      if (method.isGetter) {
        _checkAssignment(
            ReturnTypeInheritanceOrigin(source, node), FixReasonTarget.root,
            source: _currentFunctionType!.returnType!,
            destination: overriddenFieldType,
            hard: true);
      } else {
        assert(method.isSetter);
        DecoratedType currentParameterType =
            _currentFunctionType!.positionalParameters!.single!;
        DecoratedType overriddenParameterType = overriddenFieldType;
        _checkAssignment(
            ParameterInheritanceOrigin(source, node), FixReasonTarget.root,
            source: overriddenParameterType,
            destination: currentParameterType,
            hard: true);
      }
    } else {
      var decoratedOverriddenFunctionType =
          _variables!.decoratedElementType(overriddenElement);
      var overriddenFunctionType =
          decoratedOverriddenFunctionType.substitute(substitution);
      if (returnType == null) {
        _linkDecoratedTypes(
            _currentFunctionType!.returnType!,
            overriddenFunctionType.returnType,
            ReturnTypeInheritanceOrigin(source, node),
            isUnion: false);
      } else {
        _checkAssignment(
            ReturnTypeInheritanceOrigin(source, node), FixReasonTarget.root,
            source: _currentFunctionType!.returnType!,
            destination: overriddenFunctionType.returnType!,
            hard: true);
      }
      if (parameters != null) {
        int positionalParameterCount = 0;
        for (var parameter in parameters.parameters) {
          NormalFormalParameter normalParameter;
          if (parameter is NormalFormalParameter) {
            normalParameter = parameter;
          } else {
            normalParameter = (parameter as DefaultFormalParameter).parameter;
          }
          DecoratedType? currentParameterType;
          DecoratedType? overriddenParameterType;
          if (parameter.isNamed) {
            var name = normalParameter.identifier!.name;
            currentParameterType = _currentFunctionType!.namedParameters![name];
            overriddenParameterType =
                overriddenFunctionType.namedParameters![name];
          } else {
            if (positionalParameterCount <
                _currentFunctionType!.positionalParameters!.length) {
              currentParameterType = _currentFunctionType!
                  .positionalParameters![positionalParameterCount];
            }
            if (positionalParameterCount <
                overriddenFunctionType.positionalParameters!.length) {
              overriddenParameterType = overriddenFunctionType
                  .positionalParameters![positionalParameterCount];
            }
            positionalParameterCount++;
          }
          if (overriddenParameterType != null) {
            var origin = ParameterInheritanceOrigin(source, node);
            if (_isUntypedParameter(normalParameter)) {
              _linkDecoratedTypes(
                  overriddenParameterType, currentParameterType, origin,
                  isUnion: false);
            } else {
              _checkAssignment(origin, FixReasonTarget.root,
                  source: overriddenParameterType,
                  destination: currentParameterType!,
                  hard: false,
                  checkable: false);
            }
          }
        }
      }
    }
  }

  void _handleFieldOverriddenDeclaration(
      VariableDeclaration node,
      DecoratedType type,
      ClassElement classElement,
      Element overriddenElement) {
    overriddenElement = overriddenElement.declaration!;
    var overriddenClass = overriddenElement.enclosingElement as ClassElement;
    var decoratedSupertype = _decoratedClassHierarchy!
        .getDecoratedSupertype(classElement, overriddenClass);
    var substitution = decoratedSupertype.asSubstitution;
    if (overriddenElement is PropertyAccessorElement) {
      DecoratedType? unsubstitutedOverriddenType;
      if (overriddenElement.isSynthetic) {
        unsubstitutedOverriddenType =
            _variables!.decoratedElementType(overriddenElement.variable);
      } else {
        if (overriddenElement.isGetter) {
          unsubstitutedOverriddenType =
              _variables!.decoratedElementType(overriddenElement).returnType;
        } else {
          unsubstitutedOverriddenType = _variables!
              .decoratedElementType(overriddenElement)
              .positionalParameters![0];
        }
      }
      var overriddenType =
          unsubstitutedOverriddenType!.substitute(substitution);
      if (overriddenElement.isGetter) {
        _checkAssignment(
            ReturnTypeInheritanceOrigin(source, node), FixReasonTarget.root,
            source: type, destination: overriddenType, hard: true);
      } else {
        assert(overriddenElement.isSetter);
        _checkAssignment(
            ParameterInheritanceOrigin(source, node), FixReasonTarget.root,
            source: overriddenType, destination: type, hard: true);
      }
    } else {
      assert(false, 'Field overrides non-property-accessor');
    }
  }

  void _handleForLoopParts(AstNode node, ForLoopParts parts, AstNode body,
      DecoratedType? Function(AstNode) bodyHandler) {
    if (parts is ForParts) {
      if (parts is ForPartsWithDeclarations) {
        _dispatch(parts.variables);
      } else if (parts is ForPartsWithExpression) {
        var initializationType = _dispatch(parts.initialization);
        if (initializationType != null) {
          _graph.connectDummy(
              initializationType.node, DummyOrigin(source, parts));
        }
      }
      _flowAnalysis!.for_conditionBegin(node);
      if (parts.condition != null) {
        _checkExpressionNotNull(parts.condition!);
      }
      _flowAnalysis!
          .for_bodyBegin(node is Statement ? node : null, parts.condition);
    } else if (parts is ForEachParts) {
      Element? lhsElement;
      DecoratedType? lhsType;
      if (parts is ForEachPartsWithDeclaration) {
        var variableElement = parts.loopVariable.declaredElement!;
        _flowAnalysis!.declare(variableElement, true);
        lhsElement = variableElement;
        _dispatch(parts.loopVariable.type);
        lhsType = _variables!.decoratedElementType(lhsElement);
      } else if (parts is ForEachPartsWithIdentifier) {
        lhsElement = parts.identifier.staticElement;
        lhsType = _dispatch(parts.identifier);
      } else {
        throw StateError(
            'Unexpected ForEachParts subtype: ${parts.runtimeType}');
      }
      var iterableType = _checkExpressionNotNull(parts.iterable);
      DecoratedType? elementType;
      if (lhsType != null) {
        var iterableTypeType = iterableType.type!;
        if (_typeSystem.isSubtypeOf(
            iterableTypeType, typeProvider.iterableDynamicType)) {
          elementType = _decoratedClassHierarchy!
              .asInstanceOf(
                  iterableType, typeProvider.iterableDynamicType.element)
              .typeArguments[0];
          _checkAssignment(
              ForEachVariableOrigin(source, parts), FixReasonTarget.root,
              source: elementType!, destination: lhsType, hard: false);
        }
      }
      _flowAnalysis!.forEach_bodyBegin(node);
      if (lhsElement is PromotableElement) {
        _flowAnalysis!.write(node, lhsElement,
            elementType ?? _makeNullableDynamicType(node), null);
      }
    }

    // The condition may fail/iterable may be empty, so the body gets a new
    // post-dominator scope.
    _postDominatedLocals.doScoped(action: () {
      bodyHandler(body);

      if (parts is ForParts) {
        _flowAnalysis!.for_updaterBegin();
        for (var updater in parts.updaters) {
          var updaterType = _dispatch(updater)!;
          _graph.connectDummy(updaterType.node, DummyOrigin(source, updater));
        }
        _flowAnalysis!.for_end();
      } else {
        _flowAnalysis!.forEach_end();
      }
    });
  }

  void _handleGetterSetterCorrespondence(Declaration node, ClassElement? class_,
      PropertyAccessorElement getter, PropertyAccessorElement setter) {
    DecoratedType? getType;
    if (getter.isSynthetic) {
      var field = getter.variable;
      if (field.isSynthetic) return;
      getType = _variables!.decoratedElementType(field);
    } else {
      getType = _variables!.decoratedElementType(getter).returnType;
    }
    DecoratedType? setType;
    if (setter.isSynthetic) {
      var field = setter.variable;
      if (field.isSynthetic) return;
      setType = _variables!.decoratedElementType(field);
    } else {
      setType =
          _variables!.decoratedElementType(setter).positionalParameters!.single;
    }
    Map<TypeParameterElement, DecoratedType?> getterSubstitution = const {};
    Map<TypeParameterElement, DecoratedType?> setterSubstitution = const {};
    if (class_ != null) {
      var getterClass = getter.enclosingElement as ClassElement;
      if (!identical(class_, getterClass)) {
        getterSubstitution = _decoratedClassHierarchy!
            .getDecoratedSupertype(class_, getterClass)
            .asSubstitution;
      }
      var setterClass = setter.enclosingElement as ClassElement;
      if (!identical(class_, setterClass)) {
        setterSubstitution = _decoratedClassHierarchy!
            .getDecoratedSupertype(class_, setterClass)
            .asSubstitution;
      }
    }
    _checkAssignment(
        GetterSetterCorrespondenceOrigin(source, node), FixReasonTarget.root,
        source: getType!.substitute(getterSubstitution),
        destination: setType!.substitute(setterSubstitution),
        hard: true);
  }

  /// Instantiate [type] with [argumentTypes], assigning [argumentTypes] to
  /// [bounds].
  DecoratedType _handleInstantiation(DecoratedType type,
      List<DecoratedType> argumentTypes, List<EdgeOrigin> edgeOrigins) {
    for (var i = 0; i < argumentTypes.length; ++i) {
      _checkAssignment(
          edgeOrigins.elementAt(i), FixReasonTarget.root.typeArgument(i),
          source: argumentTypes[i],
          destination: DecoratedTypeParameterBounds.current!
              .get((type.type as FunctionType).typeFormals[i])!,
          hard: true);
    }

    return type.instantiate(argumentTypes);
  }

  /// Creates the necessary constraint(s) for an [ArgumentList] when invoking an
  /// executable element whose type is [calleeType].
  ///
  /// Only pass [typeArguments] or [typeArgumentTypes] depending on the use
  /// case; only one will be used.
  ///
  /// Returns the decorated return type of the invocation, after any necessary
  /// substitutions.
  DecoratedType? _handleInvocationArguments(
      AstNode node,
      Iterable<AstNode> arguments,
      TypeArgumentList? typeArguments,
      Iterable<DartType?>? typeArgumentTypes,
      DecoratedType calleeType,
      List<TypeParameterElement>? constructorTypeParameters,
      {DartType? invokeType}) {
    var typeFormals = constructorTypeParameters ?? calleeType.typeFormals!;
    var target = NullabilityNodeTarget.text('invocation').withCodeRef(node);
    if (typeFormals.isNotEmpty) {
      if (typeArguments != null) {
        var argumentTypes = typeArguments.arguments
            .map((t) => _variables!.decoratedTypeAnnotation(source, t))
            .toList();
        var origins = typeArguments.arguments
            .map((typeAnnotation) =>
                TypeParameterInstantiationOrigin(source, typeAnnotation))
            .toList();
        if (constructorTypeParameters != null) {
          calleeType = calleeType.substitute(
              Map<TypeParameterElement, DecoratedType>.fromIterables(
                  constructorTypeParameters, argumentTypes));
        } else {
          calleeType = _handleInstantiation(calleeType, argumentTypes, origins);
        }
      } else {
        if (invokeType is FunctionType) {
          var argumentTypes = typeArgumentTypes!
              .map((argType) => DecoratedType.forImplicitType(
                  typeProvider, argType, _graph, target))
              .toList();
          instrumentation?.implicitTypeArguments(source, node, argumentTypes);
          calleeType = _handleInstantiation(
              calleeType,
              argumentTypes,
              List.filled(argumentTypes.length,
                  InferredTypeParameterInstantiationOrigin(source, node)));
        } else if (constructorTypeParameters != null) {
          // No need to instantiate; caller has already substituted in the
          // correct type arguments.
        } else {
          assert(
              false,
              'invoke type should be a non-null function type, or '
              'dynamic/Function, which have no type arguments. '
              '(got $invokeType)');
        }
      }
    }
    int i = 0;
    var suppliedNamedParameters = <String>{};
    for (var argument in arguments) {
      String? name;
      Expression? expression;
      if (argument is NamedExpression) {
        name = argument.name.label.name;
        expression = argument.expression;
      } else if (argument is FormalParameter) {
        if (argument.isNamed) {
          name = argument.identifier!.name;
        }
        expression = argument.identifier;
      } else {
        expression = argument as Expression;
      }
      DecoratedType? parameterType;
      if (name != null) {
        parameterType = calleeType.namedParameters![name];
        if (parameterType == null) {
          // TODO(paulberry)
          _unimplemented(expression, 'Missing type for named parameter');
        }
        suppliedNamedParameters.add(name);
      } else {
        if (calleeType.positionalParameters!.length <= i) {
          // TODO(paulberry)
          _unimplemented(node, 'Missing positional parameter at $i');
        }
        parameterType = calleeType.positionalParameters![i++];
      }
      _handleAssignment(expression, destinationType: parameterType);
    }
    // Any parameters not supplied must be optional.
    for (var entry in calleeType.namedParameters!.entries) {
      if (suppliedNamedParameters.contains(entry.key)) continue;
      entry.value!.node!.recordNamedParameterNotSupplied(
          _guards, _graph, NamedParameterNotSuppliedOrigin(source, node));
    }
    return calleeType.returnType;
  }

  DecoratedType? _handleNullCheckHint(
      Expression expression, DecoratedType? type) {
    // Sometimes we think we're looking at an expression but we're really not
    // because we're inside a type name.  If this happens, ignore trailing
    // `/*!*/`s because they're not expression null check hints, they're type
    // non-nullability hints (which are handled by NodeBuilder).
    if (_typeNameNesting > 0) return type;
    var token = expression.endToken;
    if (_nullCheckHints.containsKey(token)) {
      // Already visited this location.
      return type;
    }
    var hint = _nullCheckHints[token] = getPostfixHint(token);
    if (hint != null && hint.kind == HintCommentKind.bang) {
      _variables!.recordNullCheckHint(source, expression, hint);
      return type!.withNode(_graph.never);
    } else {
      return type;
    }
  }

  DecoratedType? _handlePropertyAccess(Expression node, Expression? target,
      SimpleIdentifier propertyName, bool isNullAware, bool isCascaded) {
    if (!isCascaded && _isPrefix(target)) {
      return _dispatch(propertyName, skipNullCheckHint: true);
    }
    var callee = getWriteOrReadElement(propertyName);
    return _handlePropertyAccessGeneralized(
        node: node,
        target: target,
        propertyName: propertyName.name,
        isNullAware: isNullAware,
        isCascaded: isCascaded,
        inSetterContext: propertyName.inSetterContext(),
        callee: callee);
  }

  DecoratedType? _handlePropertyAccessGeneralized(
      {required Expression node,
      required Expression? target,
      required String propertyName,
      required bool isNullAware,
      required bool isCascaded,
      required bool inSetterContext,
      required Element? callee}) {
    DecoratedType? targetType;
    bool calleeIsStatic = callee is ExecutableElement && callee.isStatic;
    if (isCascaded) {
      targetType = _currentCascadeTargetType;
    } else if (calleeIsStatic) {
      _dispatch(target);
    } else if (isNullAware) {
      targetType = _dispatch(target);
    } else {
      targetType = _handleTarget(target, propertyName, callee);
    }
    DecoratedType? calleeType;
    if (targetType != null &&
        targetType.type is FunctionType &&
        propertyName == 'call') {
      // If `X` has a function type, then in the expression `X.call`, the
      // function being torn off is `X` itself, so the callee type is simply the
      // non-nullable counterpart to the type of `X`.
      var nullabilityNodeTarget =
          NullabilityNodeTarget.text('expression').withCodeRef(node);
      var nullabilityNode =
          NullabilityNode.forInferredType(nullabilityNodeTarget);
      _graph.makeNonNullableUnion(
          nullabilityNode, CallTearOffOrigin(source, node));
      calleeType = targetType.withNode(nullabilityNode);
    } else if (callee != null) {
      calleeType = getOrComputeElementType(node, callee,
          targetType: targetType, targetExpression: target);
    }
    if (calleeType == null) {
      // Dynamic dispatch.
      return _makeNullableDynamicType(node);
    }
    if (inSetterContext) {
      if (isNullAware) {
        _conditionalNodes[node] = targetType!.node;
      }
      return calleeType.positionalParameters![0];
    } else {
      var expressionType = callee is PropertyAccessorElement
          ? calleeType.returnType
          : calleeType;
      if (isNullAware) {
        expressionType = expressionType!.withNode(
            NullabilityNode.forLUB(targetType!.node, expressionType.node));
        _variables!.recordDecoratedExpressionType(node, expressionType);
      }
      return expressionType;
    }
  }

  /// Check whether [node] is a call to the quiver package's [`checkNotNull`],
  /// and if so, potentially mark the first argument as non-nullable.
  ///
  /// [`checkNotNull`]: https://pub.dev/documentation/quiver/latest/quiver.check/checkNotNull.html
  void _handleQuiverCheckNotNull(MethodInvocation node) {
    var callee = node.methodName.staticElement;
    var calleeUri = callee?.library?.source.uri;
    var isQuiverCheckNull = callee?.name == 'checkNotNull' &&
        calleeUri != null &&
        calleeUri.isScheme('package') &&
        calleeUri.path.startsWith('quiver/');

    if (isQuiverCheckNull && node.argumentList.arguments.isNotEmpty) {
      var argument = node.argumentList.arguments.first;
      if (argument is SimpleIdentifier && _isReferenceInScope(argument)) {
        var argumentType =
            getOrComputeElementType(argument, argument.staticElement!);
        _graph.makeNonNullable(
            argumentType.node, QuiverCheckNotNullOrigin(source, argument));
      }
    }
  }

  DecoratedType? _handleTarget(
      Expression? target, String name, Element? callee) {
    if (isDeclaredOnObject(name)) {
      return _dispatch(target);
    } else if ((callee is MethodElement || callee is PropertyAccessorElement) &&
        callee!.enclosingElement is ExtensionElement) {
      // Extension methods can be called on a `null` target, when the `on` type
      // of the extension is nullable.  Note: we don't need to check whether the
      // target type is assignable to the extended type; that is done in
      // [getOrComputeElementType].
      return _dispatch(target);
    } else {
      return _checkExpressionNotNull(target!);
    }
  }

  void _handleUninitializedFields(AstNode node, Set<FieldElement?> fields) {
    for (var field in fields) {
      _graph.makeNullable(_variables!.decoratedElementType(field!).node!,
          FieldNotInitializedOrigin(source, node));
    }
  }

  /// Returns whether [_currentFunctionExpression] is an argument to the test
  /// package's `setUp` function.
  bool _isCurrentFunctionExpressionFoundInTestSetUpCall() {
    var parent = _currentFunctionExpression?.parent;
    if (parent is ArgumentList) {
      var grandParent = parent.parent;
      if (grandParent is MethodInvocation) {
        var enclosingInvocation = grandParent.methodName;
        if (enclosingInvocation.name == 'setUp') {
          var uri = enclosingInvocation.staticElement!.library?.source.uri;
          if (uri != null &&
              uri.isScheme('package') &&
              uri.path.startsWith('test_core/')) {
            return true;
          }
        }
      }
    }
    return false;
  }

  bool _isPrefix(Expression? e) =>
      e is SimpleIdentifier && e.staticElement is PrefixElement;

  bool _isReferenceInScope(Expression expression) {
    var element = _referencedElement(expression);
    return element != null && _postDominatedLocals.isInScope(element);
  }

  bool _isUntypedParameter(NormalFormalParameter parameter) {
    if (parameter is SimpleFormalParameter) {
      return parameter.type == null;
    } else if (parameter is FieldFormalParameter) {
      return parameter.type == null;
    } else {
      return false;
    }
  }

  void _linkDecoratedTypeParameters(
      DecoratedType x, DecoratedType? y, EdgeOrigin origin,
      {bool isUnion = true}) {
    for (int i = 0;
        i < x.positionalParameters!.length &&
            i < y!.positionalParameters!.length;
        i++) {
      _linkDecoratedTypes(
          x.positionalParameters![i]!, y.positionalParameters![i], origin,
          isUnion: isUnion);
    }
    for (var entry in x.namedParameters!.entries) {
      var superParameterType = y!.namedParameters![entry.key];
      if (superParameterType != null) {
        _linkDecoratedTypes(entry.value!, y.namedParameters![entry.key], origin,
            isUnion: isUnion);
      }
    }
  }

  void _linkDecoratedTypes(DecoratedType x, DecoratedType? y, EdgeOrigin origin,
      {bool isUnion = true}) {
    if (isUnion) {
      _graph.union(x.node!, y!.node!, origin);
    } else {
      _graph.connect(x.node, y!.node!, origin, hard: true);
    }
    _linkDecoratedTypeParameters(x, y, origin, isUnion: isUnion);
    for (int i = 0;
        i < x.typeArguments.length && i < y.typeArguments.length;
        i++) {
      _linkDecoratedTypes(x.typeArguments[i]!, y.typeArguments[i], origin,
          isUnion: isUnion);
    }
    if (x.returnType != null && y.returnType != null) {
      _linkDecoratedTypes(x.returnType!, y.returnType, origin,
          isUnion: isUnion);
    }
  }

  EdgeOrigin _makeEdgeOrigin(DecoratedType sourceType, Expression? expression,
      {bool isSetupAssignment = false}) {
    if (sourceType.type!.isDynamic) {
      return DynamicAssignmentOrigin(source, expression);
    } else {
      ExpressionChecksOrigin expressionChecksOrigin = ExpressionChecksOrigin(
          source, expression, ExpressionChecks(),
          isSetupAssignment: isSetupAssignment);
      _variables!
          .recordExpressionChecks(source, expression!, expressionChecksOrigin);
      return expressionChecksOrigin;
    }
  }

  DecoratedType _makeNonNullableBoolType(Expression expression) {
    assert(expression.staticType!.isDartCoreBool);
    var target =
        NullabilityNodeTarget.text('expression').withCodeRef(expression);
    var nullabilityNode = NullabilityNode.forInferredType(target);
    _graph.makeNonNullableUnion(
        nullabilityNode, NonNullableBoolTypeOrigin(source, expression));
    return DecoratedType(typeProvider.boolType, nullabilityNode);
  }

  DecoratedType _makeNonNullLiteralType(Expression expression,
      {List<DecoratedType?> typeArguments = const []}) {
    var target =
        NullabilityNodeTarget.text('expression').withCodeRef(expression);
    var nullabilityNode = NullabilityNode.forInferredType(target);
    _graph.makeNonNullableUnion(
        nullabilityNode, LiteralOrigin(source, expression));
    return DecoratedType(expression.staticType, nullabilityNode,
        typeArguments: typeArguments);
  }

  DecoratedType _makeNullableDynamicType(AstNode astNode) {
    var target =
        NullabilityNodeTarget.text('dynamic type').withCodeRef(astNode);
    var decoratedType = DecoratedType.forImplicitType(
        typeProvider, typeProvider.dynamicType, _graph, target);
    _graph.makeNullable(
        decoratedType.node!, AlwaysNullableTypeOrigin(source, astNode, false));
    return decoratedType;
  }

  DecoratedType _makeNullableVoidType(SimpleIdentifier astNode) {
    var target = NullabilityNodeTarget.text('void type').withCodeRef(astNode);
    var decoratedType = DecoratedType.forImplicitType(
        typeProvider, typeProvider.voidType, _graph, target);
    _graph.makeNullable(
        decoratedType.node!, AlwaysNullableTypeOrigin(source, astNode, true));
    return decoratedType;
  }

  NullabilityNode _nullabilityNodeForGLB(
      AstNode astNode, NullabilityNode leftNode, NullabilityNode rightNode) {
    var node = NullabilityNode.forGLB();
    var origin = GreatestLowerBoundOrigin(source, astNode);
    _graph.connect(leftNode, node, origin, guards: [rightNode]);
    _graph.connect(node, leftNode, origin);
    _graph.connect(node, rightNode, origin);
    return node;
  }

  /// Returns the element referenced directly by [expression], if any; otherwise
  /// returns `null`.
  Element? _referencedElement(Expression expression) {
    expression = expression.unParenthesized;
    if (expression is SimpleIdentifier) {
      return _favorFieldFormalElements(expression.staticElement);
    } else if (expression is ThisExpression || expression is SuperExpression) {
      return _extensionThis;
    } else {
      return null;
    }
  }

  /// Determines whether uses of [expression] should cause hard edges to be
  /// created in the nullability graph.
  ///
  /// If [isConditionallyExecuted] is `true`, that indicates that [expression]
  /// appears in a context where it might not get executed (e.g. on the RHS of
  /// a `??=`).
  bool _shouldUseHardEdge(Expression expression,
      {bool isConditionallyExecuted = false}) {
    expression = expression.unParenthesized;
    if (expression is ListLiteral || expression is SetOrMapLiteral) {
      // List, set, and map literals have either explicit or implicit type
      // arguments.  If supplying a nullable type for one of these type
      // arguments would lead to an error (e.g. `f(<int?>[])` where `f` requires
      // a `List<int>`), then we should use a hard edge, to ensure that the
      // migrated type argument will be non-nullable.
      return true;
    } else if (expression is AsExpression) {
      // "as" expressions have an explicit type.  If making this type nullable
      // would lead to an error (e.g. `f(x as int?)` where `f` requires an
      // `int`),then we should use a hard edge, to ensure that the migrated type
      // will be non-nullable.
      return true;
    }
    // For other expressions, we should use a hard edge only if (a) the
    // expression is unconditionally executed, and (b) the expression is a
    // reference to a local variable or parameter and it post-dominates the
    // declaration of that local variable or parameter.
    return !isConditionallyExecuted && _isReferenceInScope(expression);
  }

  DecoratedType? _thisOrSuper(Expression node) {
    if (_currentClassOrExtension == null) {
      return null;
    }

    NullabilityNode makeNonNullableNode(NullabilityNodeTarget target) {
      var nullabilityNode = NullabilityNode.forInferredType(target);
      _graph.makeNonNullableUnion(nullabilityNode,
          ThisOrSuperOrigin(source, node, node is ThisExpression));
      return nullabilityNode;
    }

    var token = node.beginToken.lexeme;
    var target =
        NullabilityNodeTarget.text('$token expression').withCodeRef(node);
    if (_currentClassOrExtension is ClassElement) {
      final type = (_currentClassOrExtension as ClassElement).thisType;

      // Instantiate the type, and any type arguments, with non-nullable types,
      // because the type of `this` is always `ClassName<Param, Param, ...>`
      // with no `?`s.  (Even if some of the type parameters are allowed to be
      // instantiated with nullable types at runtime, a reference to `this`
      // can't be migrated in such a way that forces them to be nullable.)
      var index = 0;
      return DecoratedType(type, makeNonNullableNode(target),
          typeArguments: type.typeArguments
              .map((t) => DecoratedType(
                  t, makeNonNullableNode(target.typeArgument(index++))))
              .toList());
    } else {
      assert(_currentClassOrExtension is ExtensionElement);
      assert(_currentExtendedType != null);
      return _currentExtendedType;
    }
  }

  /// If [node] is an `orElse` argument to an iterable method that should be
  /// transformed, performs the necessary assignment checks on the expression
  /// type and returns `true` (this indicates to the caller that no further
  /// assignment checks need to be performed); otherwise returns `false`.
  bool _tryTransformOrElse(Expression? expression, DecoratedType sourceType) {
    var transformationInfo =
        _whereOrNullTransformer.tryTransformOrElseArgument(expression);
    if (transformationInfo != null) {
      // Don't build any edges for this argument; if necessary we'll transform
      // it rather than make things nullable.  But do save the nullability of
      // the return value of the `orElse` method, so that we can later connect
      // it to the nullability of the value returned from the method
      // invocation.
      var extraNullability = sourceType.returnType!.node;
      _deferredMethodInvocationProcessing[transformationInfo.methodInvocation] =
          (methodInvocationType) {
        var newNode = NullabilityNode.forInferredType(
            NullabilityNodeTarget.text(
                'return value from ${transformationInfo.originalName}'));
        var origin = IteratorMethodReturnOrigin(
            source, transformationInfo.methodInvocation);
        _graph.connect(methodInvocationType!.node, newNode, origin);
        _graph.connect(extraNullability, newNode, origin);
        return methodInvocationType.withNode(newNode);
      };
      return true;
    } else {
      return false;
    }
  }

  /// If [node] is a call to `Iterable.where` that should be transformed,
  /// performs the necessary assignment checks on the expression type and
  /// returns `true` (this indicates to the caller that no further assignment
  /// checks need to be performed); otherwise returns `false`.
  bool _tryTransformWhere(Expression? expression, EdgeOrigin edgeOrigin,
      DecoratedType sourceType, DecoratedType destinationType) {
    var transformationInfo =
        _whereNotNullTransformer.tryTransformMethodInvocation(expression);
    if (transformationInfo != null) {
      _checkAssignment(edgeOrigin, FixReasonTarget.root,
          source: _whereNotNullTransformer.transformDecoratedInvocationType(
              sourceType, _graph),
          destination: destinationType,
          hard: false);
      return true;
    } else {
      return false;
    }
  }

  Never _unimplemented(AstNode? node, String message) {
    StringBuffer buffer = StringBuffer();
    buffer.write(message);
    if (node != null) {
      CompilationUnit unit = node.root as CompilationUnit;
      buffer.write(' in "');
      buffer.write(node.toSource());
      buffer.write('" on line ');
      buffer.write(unit.lineInfo.getLocation(node.offset).lineNumber);
      buffer.write(' of "');
      buffer.write(unit.declaredElement!.source.fullName);
      buffer.write('"');
    }
    throw UnimplementedError(buffer.toString());
  }

  /// Produce Future<flatten(T)> for some T, however, we would like to merely
  /// upcast T to that type if possible, skipping the flatten when not
  /// necessary.
  DecoratedType _wrapFuture(DecoratedType type, AstNode? node) {
    var dartType = type.type!;
    if (dartType.isDartCoreNull || dartType.isBottom) {
      return _futureOf(type, node!);
    }

    if (dartType is InterfaceType &&
        dartType.element == typeProvider.futureOrElement) {
      var typeArguments = type.typeArguments;
      if (typeArguments.length == 1) {
        // Wrapping FutureOr<T?1>?2 should produce Future<T?3>, where either 1
        // or 2 being nullable causes 3 to become nullable.
        var typeArgument = typeArguments[0]!;
        return _futureOf(
            typeArgument
                .withNode(NullabilityNode.forLUB(typeArgument.node, type.node)),
            node!);
      }
    }

    if (_typeSystem.isSubtypeOf(dartType, typeProvider.futureDynamicType)) {
      return _decoratedClassHierarchy!
          .asInstanceOf(type, typeProvider.futureDynamicType.element);
    }

    return _futureOf(type, node!);
  }

  /// If the [node] is the finishing identifier of an assignment, return its
  /// "writeElement", otherwise return its "staticElement", which might be
  /// thought as the "readElement".
  static Element? getWriteOrReadElement(AstNode node) {
    var writeElement = _getWriteElement(node);
    if (writeElement != null) {
      return writeElement;
    }

    if (node is IndexExpression) {
      return node.staticElement;
    } else if (node is SimpleIdentifier) {
      return node.staticElement;
    } else {
      return null;
    }
  }

  /// If the [node] is the target of a [CompoundAssignmentExpression],
  /// return the corresponding "writeElement", which is the local variable,
  /// the setter referenced with a [SimpleIdentifier] or a [PropertyAccess],
  /// or the `[]=` operator.
  static Element? _getWriteElement(AstNode node) {
    var parent = node.parent;
    if (parent is AssignmentExpression && parent.leftHandSide == node) {
      return parent.writeElement;
    } else if (parent is PostfixExpression) {
      return parent.writeElement;
    } else if (parent is PrefixExpression) {
      return parent.writeElement;
    }

    if (parent is PrefixedIdentifier && parent.identifier == node) {
      return _getWriteElement(parent);
    } else if (parent is PropertyAccess && parent.propertyName == node) {
      return _getWriteElement(parent);
    } else {
      return null;
    }
  }
}

/// Implementation of [_checkAssignment] for [EdgeBuilder].
///
/// This has been moved to its own mixin to allow it to be more easily unit
/// tested.
mixin _AssignmentChecker {
  TypeProvider get typeProvider;

  DecoratedClassHierarchy? get _decoratedClassHierarchy;

  TypeSystem get _typeSystem;

  /// Creates the necessary constraint(s) for an assignment from [source] to
  /// [destination].  [origin] should be used as the origin for any edges
  /// created.  [hard] indicates whether a hard edge should be created.
  /// [sourceIsFunctionLiteral] indicates whether the source of the assignment
  /// is a function literal expression.
  void _checkAssignment(EdgeOrigin origin, FixReasonTarget edgeTarget,
      {required DecoratedType source,
      required DecoratedType destination,
      required bool hard,
      bool checkable = true,
      bool sourceIsFunctionLiteral = false}) {
    var sourceType = source.type!;
    var destinationType = destination.type!;
    if (!_typeSystem.isSubtypeOf(sourceType, destinationType)) {
      // Not a proper upcast assignment.
      if (_typeSystem.isSubtypeOf(destinationType, sourceType)) {
        // But rather a downcast.
        _checkDowncast(origin,
            source: source, destination: destination, hard: hard);
        return;
      }
      if (destinationType is FunctionType) {
        var callMethodType = _getCallMethodType(source);
        if (callMethodType != null) {
          // Handle implicit `.call` coercion
          _checkAssignment(origin, edgeTarget,
              source: callMethodType,
              destination: destination,
              hard: false,
              checkable: false,
              sourceIsFunctionLiteral: sourceIsFunctionLiteral);
          return;
        }
      }
      // A side cast. This may be an explicit side cast, or illegal code. There
      // is no nullability we can infer here.
      assert(
          _assumeNonNullabilityInCasts,
          'side cast not supported without assuming non-nullability:'
          ' $sourceType to $destinationType');
      _connect(source.node, destination.node, origin, edgeTarget, hard: hard);
      return;
    }
    _connect(source.node, destination.node, origin, edgeTarget,
        hard: hard, checkable: checkable);
    _checkAssignment_recursion(origin, edgeTarget,
        source: source,
        destination: destination,
        sourceIsFunctionLiteral: sourceIsFunctionLiteral,
        hard: hard);
  }

  /// Does the recursive part of [_checkAssignment], visiting all of the types
  /// constituting [source] and [destination], and creating the appropriate
  /// edges between them.  [sourceIsFunctionLiteral] indicates whether the
  /// source of the assignment is a function literal expression.
  void _checkAssignment_recursion(EdgeOrigin origin, FixReasonTarget edgeTarget,
      {required DecoratedType source,
      required DecoratedType destination,
      bool sourceIsFunctionLiteral = false,
      bool hard = false}) {
    var sourceType = source.type!;
    var destinationType = destination.type!;
    assert(_typeSystem.isSubtypeOf(sourceType, destinationType));
    if (destinationType.isDartAsyncFutureOr) {
      var s1 = destination.typeArguments[0];
      if (sourceType.isDartAsyncFutureOr) {
        // This is a special case not in the subtyping spec.  The subtyping spec
        // covers this case by expanding the LHS first, which is fine but
        // leads to redundant edges (which might be confusing for users)
        // if T0 is FutureOr<S0> then:
        // - T0 <: T1 iff Future<S0> <: T1 and S0 <: T1
        // Since T1 is FutureOr<S1>, this is equivalent to:
        // - T0 <: T1 iff (Future<S0> <: Future<S1> or Future<S0> <: S1) and
        //                (S0 <: Future<S1> or S0 <: S1)
        // Which is equivalent to:
        // - T0 <: T1 iff (S0 <: S1 or Future<S0> <: S1) and
        //                (S0 <: Future<S1> or S0 <: S1)
        // Which is equivalent to (distributing the "and"):
        // - T0 <: T1 iff (S0 <: S1 and (S0 <: Future<S1> or S0 <: S1)) or
        //                (Future<S0> <: S1 and (S0 <: Future<S1> or S0 <: S1))
        // Which is equivalent to (distributing the "and"s):
        // - T0 <: T1 iff (S0 <: S1 and S0 <: Future<S1>) or
        //                (S0 <: S1 and S0 <: S1) or
        //                (Future<S0> <: S1 and S0 <: Future<S1>) or
        //                (Future<S0> <: S1 and S0 <: S1)
        // If S0 <: S1, the relation is satisfied.  Otherwise the only term that
        // matters is (Future<S0> <: S1 and S0 <: Future<S1>), so this is
        // equivalent to:
        // - T0 <: T1 iff S0 <: S1 or (Future<S0> <: S1 and S0 <: Future<S1>)
        // Let's consider whether there are any cases where the RHS of this "or"
        // can be satisfied but not the LHS.  That is, assume that
        // Future<S0> <: S1 and S0 <: Future<S1> hold, but not S0 <: S1.  S1
        // must not be a top type (otherwise S0 <: S1 would hold), so the only
        // way Future<S0> <: S1 can hold is if S1 is Future<A> or FutureOr<A>
        // for some A.  In either case, Future<S1> simplifies to Future<A>, so
        // we know that S0 <: Future<A>.  Also, in either case, Future<A> <: S1.
        // Combining these, we have that S0 <: S1, contradicting our assumption.
        // So the RHS of the "or" is redundant, and we can simplify to:
        // - S0 <: S1.
        var s0 = source.typeArguments[0]!;
        _checkAssignment(origin, edgeTarget.yieldedType,
            source: s0, destination: s1!, hard: false);
        return;
      }
      // (From the subtyping spec):
      // if T1 is FutureOr<S1> then T0 <: T1 iff any of the following hold:
      // - either T0 <: Future<S1>
      if (_typeSystem.isSubtypeOf(
          sourceType, typeProvider.futureType(s1!.type!))) {
        // E.g. FutureOr<int> = (... as Future<int>)
        // This is handled by the InterfaceType logic below, since we treat
        // FutureOr as a supertype of Future.
      }
      // - or T0 <: S1
      else if (_typeSystem.isSubtypeOf(sourceType, s1.type!)) {
        // E.g. FutureOr<int> = (... as int)
        _checkAssignment_recursion(origin, edgeTarget.yieldedType,
            source: source, destination: s1);
        return;
      }
      // - or T0 is X0 and X0 has bound S0 and S0 <: T1
      // - or T0 is X0 & S0 and S0 <: T1
      else if (sourceType is TypeParameterType) {
        throw UnimplementedError('TODO(paulberry)');
      } else {
        // Not a subtype.  This should never happen, since we handle the
        // implicit downcast case above.
        assert(false, 'not a subtype');
      }
    }
    if (sourceType.isBottom || sourceType.isDartCoreNull) {
      // No further edges need to be created, since all types are trivially
      // supertypes of bottom (and of Null, in the pre-migration world).
    } else if (sourceType is TypeParameterType) {
      // Handle this before handling dynamic/object/void, to correctly infer
      // nullabilities in `Object o = T`.
      if (destinationType is TypeParameterType) {
        // No further edges need to be created, since type parameter types
        // aren't made up of other types.
      } else {
        // Effectively this is an assignment from the type parameter's bound to
        // the destination type.
        _checkAssignment(origin, edgeTarget,
            source: _getTypeParameterTypeBound(source)!,
            destination: destination,
            hard: false);
        return;
      }
    } else if (destinationType.isDynamic ||
        destinationType.isVoid ||
        destinationType.isDartCoreObject) {
      // No further edges need to be created, since all types are trivially
      // subtypes of dynamic, Object, and void, since all are treated as
      // equivalent to dynamic for subtyping purposes.
    } else if (sourceType is InterfaceType &&
        destinationType is InterfaceType) {
      var rewrittenSource = _decoratedClassHierarchy!
          .asInstanceOf(source, destinationType.element);
      assert(rewrittenSource.typeArguments.length ==
          destination.typeArguments.length);
      for (int i = 0; i < rewrittenSource.typeArguments.length; i++) {
        _checkAssignment(origin, edgeTarget.typeArgument(i),
            source: rewrittenSource.typeArguments[i]!,
            destination: destination.typeArguments[i]!,
            hard: hard,
            checkable: false);
      }
    } else if (sourceType is FunctionType && destinationType is FunctionType) {
      // If the source is a function literal, we want a hard edge, so that if a
      // function returning non-null is required, we will insure that the
      // function literal has a non-nullable return type (e.g. by inserting null
      // checks into the function literal).
      _checkAssignment(origin, edgeTarget.returnType,
          source: source.returnType!,
          destination: destination.returnType!,
          hard: sourceIsFunctionLiteral,
          checkable: false);
      if (source.typeArguments.isNotEmpty ||
          destination.typeArguments.isNotEmpty) {
        throw UnimplementedError('TODO(paulberry)');
      }
      for (int i = 0;
          i < source.positionalParameters!.length &&
              i < destination.positionalParameters!.length;
          i++) {
        // Note: source and destination are swapped due to contravariance.
        _checkAssignment(origin, edgeTarget.positionalParameter(i),
            source: destination.positionalParameters![i]!,
            destination: source.positionalParameters![i]!,
            hard: false,
            checkable: false);
      }
      for (var entry in destination.namedParameters!.entries) {
        // Note: source and destination are swapped due to contravariance.
        _checkAssignment(origin, edgeTarget.namedParameter(entry.key),
            source: entry.value!,
            destination: source.namedParameters![entry.key]!,
            hard: false,
            checkable: false);
      }
    } else if (destinationType.isDynamic || sourceType.isDynamic) {
      // ok; nothing further to do.
    } else if (destinationType is InterfaceType && sourceType is FunctionType) {
      // Either this is an upcast to Function or Object, or it is erroneous
      // code.  In either case we don't need to create any additional edges.
    } else {
      throw '$destination <= $source'; // TODO(paulberry)
    }
  }

  void _checkDowncast(EdgeOrigin origin,
      {required DecoratedType source,
      required DecoratedType destination,
      required bool hard}) {
    var destinationType = destination.type!;
    assert(_typeSystem.isSubtypeOf(destinationType, source.type!));
    // Nullability should narrow to maintain subtype relationship.
    _connect(source.node, destination.node, origin, FixReasonTarget.root,
        hard: hard);

    if (source.type!.isDynamic ||
        source.type!.isDartCoreObject ||
        source.type!.isVoid) {
      if (destinationType is InterfaceType) {
        for (final param in destinationType.element.typeParameters) {
          assert(param.bound == null,
              'downcast to type parameters with bounds not supported');
        }
      }
      if (destinationType is FunctionType) {
        // Nothing else to do.
        return;
      }
    } else if (destinationType.isDartCoreNull) {
      // There's not really much we can infer from trying to assign a type to
      // Null.  We could say that the source of the assignment must be nullable,
      // but that's not really useful because the nullability won't propagate
      // anywhere.  Besides, the code is probably erroneous (e.g. the user is
      // trying to store a value into a `List<Null>`).  So do nothing.
      return;
    } else if (destinationType is TypeParameterType) {
      if (source.type is! TypeParameterType) {
        // Assume an assignment to the type parameter's bound.
        _checkAssignment(origin, FixReasonTarget.root,
            source: source,
            destination: _getTypeParameterTypeBound(destination)!,
            hard: false);
      } else if (destinationType == source.type) {
        // Nothing to do.
        return;
      }
    } else if (source.type!.isDartAsyncFutureOr) {
      if (destination.type!.isDartAsyncFuture) {
        // FutureOr<T?> is nullable, so the Future<T> should be nullable too.
        _connect(source.typeArguments[0]!.node, destination.node, origin,
            FixReasonTarget.root.yieldedType,
            hard: hard);
        _checkDowncast(origin,
            source: source.typeArguments[0]!,
            destination: destination.typeArguments[0]!,
            hard: false);
      } else if (destination.type!.isDartAsyncFutureOr) {
        _checkDowncast(origin,
            source: source.typeArguments[0]!,
            destination: destination.typeArguments[0]!,
            hard: false);
      } else {
        _checkDowncast(origin,
            source: source.typeArguments[0]!,
            destination: destination,
            hard: false);
      }
    } else if (destinationType is InterfaceType) {
      if (source.type is InterfaceType) {
        final target = _decoratedClassHierarchy!
            .asInstanceOf(destination, source.type!.element as ClassElement?);
        for (var i = 0; i < source.typeArguments.length; ++i) {
          _checkDowncast(origin,
              source: source.typeArguments[i]!,
              destination: target.typeArguments[i]!,
              hard: false);
        }
      } else {
        assert(false,
            'downcasting from ${source.type.runtimeType} to interface type');
      }
    } else if (destinationType is FunctionType) {
      if (source.type!.isDartCoreFunction) {
        // Nothing else to do.
        return;
      }
    } else {
      assert(
          false,
          'downcasting from ${source.type.runtimeType} to '
          '${destinationType.runtimeType} not supported. (${source.type} $destinationType)');
    }
  }

  void _connect(NullabilityNode? source, NullabilityNode? destination,
      EdgeOrigin origin, FixReasonTarget edgeTarget,
      {bool hard = false, bool checkable = true});

  /// If [type] represents a class containing a `call` method, returns the
  /// decorated type of the `call` method, with appropriate substitutions.
  /// Otherwise returns `null`.
  DecoratedType? _getCallMethodType(DecoratedType type);

  /// Given a [type] representing a type parameter, retrieves the type's bound.
  DecoratedType? _getTypeParameterTypeBound(DecoratedType type);
}

/// Information about a binary expression whose boolean value could possibly
/// affect nullability analysis.
class _ConditionInfo {
  /// The [expression] of interest.
  final Expression condition;

  /// Indicates whether [condition] is pure (free from side effects).
  ///
  /// For example, a condition like `x == null` is pure (assuming `x` is a local
  /// variable or static variable), because evaluating it has no user-visible
  /// effect other than returning a boolean value.
  final bool isPure;

  /// Indicates whether the intents postdominate the intent node declarations.
  final bool? postDominatingIntent;

  /// If not `null`, the [NullabilityNode] that would need to be nullable in
  /// order for [condition] to evaluate to `true`.
  final NullabilityNode? trueGuard;

  /// If not `null`, the [NullabilityNode] that would need to be nullable in
  /// order for [condition] to evaluate to `false`.
  final NullabilityNode? falseGuard;

  /// If not `null`, the [NullabilityNode] that should be asserted to have
  /// non-null intent if [condition] is asserted to be `true`.
  final NullabilityNode? trueDemonstratesNonNullIntent;

  /// If not `null`, the [NullabilityNode] that should be asserted to have
  /// non-null intent if [condition] is asserted to be `false`.
  final NullabilityNode? falseDemonstratesNonNullIntent;

  _ConditionInfo(this.condition,
      {required this.isPure,
      this.postDominatingIntent,
      this.trueGuard,
      this.falseGuard,
      this.trueDemonstratesNonNullIntent,
      this.falseDemonstratesNonNullIntent});

  /// Returns a new [_ConditionInfo] describing the boolean "not" of `this`.
  _ConditionInfo not(Expression condition) => _ConditionInfo(condition,
      isPure: isPure,
      postDominatingIntent: postDominatingIntent,
      trueGuard: falseGuard,
      falseGuard: trueGuard,
      trueDemonstratesNonNullIntent: falseDemonstratesNonNullIntent,
      falseDemonstratesNonNullIntent: trueDemonstratesNonNullIntent);
}

extension on DartType? {
  DartType? get explicitBound {
    final self = this;
    if (self is TypeParameterType &&
        self.nullabilitySuffix == NullabilitySuffix.star) {
      return self.element.bound.explicitBound;
    }
    return self;
  }
}
