// Copyright (c) 2022, 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 '../flow_analysis/flow_analysis.dart';
import 'type_analysis_result.dart';
import 'type_operations.dart';

/// Information supplied by the client to [TypeAnalyzer.analyzeSwitchExpression]
/// or [TypeAnalyzer.analyzeSwitchStatement] about a single case head or
/// `default` clause.
///
/// The client is free to `implement` or `extend` this class.
class CaseHeadOrDefaultInfo<Node extends Object, Expression extends Node,
    Variable extends Object> {
  /// For a `case` clause, the case pattern.  For a `default` clause, `null`.
  final Node? pattern;

  /// The pattern variables declared in [pattern]. Some of them are joins of
  /// individual pattern variable declarations. We don't know their types
  /// until we do type analysis. So, some of these variables might become
  /// not consistent.
  final Map<String, Variable> variables;

  /// For a `case` clause that has a guard clause, the expression following
  /// `when`.  Otherwise `null`.
  final Expression? guard;

  CaseHeadOrDefaultInfo({
    required this.pattern,
    required this.variables,
    this.guard,
  });
}

/// The kind of inconsistency identified for a variable.
enum JoinedPatternVariableInconsistency {
  /// No inconsistency.
  none(0),

  /// Only one branch of a logical-or pattern has the variable.
  logicalOr(4),

  /// Not every case of a shared case scope has the variable.
  sharedCaseAbsent(3),

  /// The shared case scope has a label or `default` case.
  sharedCaseHasLabel(2),

  /// The finality or type of the variable components is not the same.
  /// This is reported for both logical-or and shared cases.
  differentFinalityOrType(1);

  final int _severity;

  const JoinedPatternVariableInconsistency(this._severity);

  /// Returns the most serious inconsistency for `this` or [other].
  JoinedPatternVariableInconsistency maxWith(
    JoinedPatternVariableInconsistency other,
  ) {
    return _severity > other._severity ? this : other;
  }

  /// Returns the most serious inconsistency for `this` or [others].
  JoinedPatternVariableInconsistency maxWithAll(
    Iterable<JoinedPatternVariableInconsistency> others,
  ) {
    JoinedPatternVariableInconsistency result = this;
    for (JoinedPatternVariableInconsistency other in others) {
      result = result.maxWith(other);
    }
    return result;
  }
}

/// The location where the join of a pattern variable happens.
enum JoinedPatternVariableLocation {
  /// A single pattern, from `logical-or` patterns.
  singlePattern,

  /// A shared `case` scope, when multiple `case`s share the same body.
  sharedCaseScope,
}

class MapPatternEntry<Expression extends Object, Pattern extends Object> {
  final Expression key;
  final Pattern value;

  MapPatternEntry({
    required this.key,
    required this.value,
  });
}

class NamedType<Type extends Object> {
  final String name;
  final Type type;

  NamedType(this.name, this.type);
}

/// Information supplied by the client to [TypeAnalyzer.analyzeObjectPattern],
/// [TypeAnalyzer.analyzeRecordPattern], or
/// [TypeAnalyzer.analyzeRecordPatternSchema] about a single field in a record
/// or object pattern.
///
/// The client is free to `implement` or `extend` this class.
class RecordPatternField<Node extends Object, Pattern extends Object> {
  /// The client specific node from which this object was created.  It can be
  /// used for error reporting.
  final Node node;

  /// If not `null` then the field is named, otherwise it is positional.
  final String? name;
  final Pattern pattern;

  RecordPatternField({
    required this.node,
    required this.name,
    required this.pattern,
  });
}

class RecordType<Type extends Object> {
  final List<Type> positional;
  final List<NamedType<Type>> named;

  RecordType({
    required this.positional,
    required this.named,
  });
}

/// Kinds of relational pattern operators that shared analysis needs to
/// distinguish.
enum RelationalOperatorKind {
  /// The operator `==`
  equals,

  /// The operator `!=`
  notEquals,

  /// Any relational pattern operator other than `==` or `!=`
  other,
}

/// Information about a relational operator.
class RelationalOperatorResolution<Type extends Object> {
  final RelationalOperatorKind kind;
  final Type parameterType;
  final Type returnType;

  RelationalOperatorResolution({
    required this.kind,
    required this.parameterType,
    required this.returnType,
  });
}

/// Information supplied by the client to [TypeAnalyzer.analyzeSwitchExpression]
/// about an individual `case` or `default` clause.
///
/// The client is free to `implement` or `extend` this class.
class SwitchExpressionMemberInfo<Node extends Object, Expression extends Node,
    Variable extends Object> {
  /// The [CaseOrDefaultHead] associated with this clause.
  final CaseHeadOrDefaultInfo<Node, Expression, Variable> head;

  /// The body of the `case` or `default` clause.
  final Expression expression;

  SwitchExpressionMemberInfo({required this.head, required this.expression});
}

/// Information supplied by the client to [TypeAnalyzer.analyzeSwitchStatement]
/// about an individual `case` or `default` clause.
///
/// The client is free to `implement` or `extend` this class.
class SwitchStatementMemberInfo<Node extends Object, Statement extends Node,
    Expression extends Node, Variable extends Object> {
  /// The list of case heads for this case.
  ///
  /// The reason this is a list rather than a single head is because the front
  /// end merges together cases that share a body at parse time.
  final List<CaseHeadOrDefaultInfo<Node, Expression, Variable>> heads;

  /// Is `true` if the group of `case` and `default` clauses has a label.
  final bool hasLabels;

  /// The statements following this `case` or `default` clause.  If this list is
  /// empty, and this is not the last `case` or `default` clause, this clause
  /// will be considered to share a body with the `case` or `default` clause
  /// that follows.
  final List<Statement> body;

  /// The merged set of pattern variables from [heads]. If there is more than
  /// one element in [heads], these variables are joins of individual pattern
  /// variable declarations. Some of these variables might be already not
  /// consistent, because they are present not in every head. We don't know
  /// their types until we do type analysis. So, some of these variables
  /// might become not consistent.
  final Map<String, Variable> variables;

  SwitchStatementMemberInfo(
      {required this.heads,
      required this.body,
      required this.variables,
      required this.hasLabels});
}

/// Type analysis logic to be shared between the analyzer and front end.  The
/// intention is that the client's main type inference visitor class can include
/// this mix-in and call shared analysis logic as needed.
///
/// Concrete methods in this mixin, typically named `analyzeX` for some `X`,
/// are intended to be called by the client in order to analyze an AST node (or
/// equivalent) of type `X`; a client's `visit` method shouldn't have to do much
/// than call the corresponding `analyze` method, passing in AST node's children
/// and other properties, possibly take some client-specific actions with the
/// returned value (such as storing intermediate inference results), and then
/// return the returned value up the call stack.
///
/// Abstract methods in this mixin are intended to be implemented by the client;
/// these are called by the `analyzeX` methods to report analysis results, to
/// query the client-specific information (e.g. to obtain the client's
/// representation of core types), and to trigger recursive analysis of child
/// AST nodes.
///
/// Note that calling an `analyzeX` method is guaranteed to call `dispatch` on
/// all its subexpressions.  However, we don't specify the precise order in
/// which this will happen, nor do we always specify which callbacks will be
/// invoked during analysis, because these details are considered part of the
/// implementation of type analysis, not its API.  Instead, we specify the
/// effect that each method has on a conceptual "stack" of entities.
///
/// In documentation, the entities in the stack are listed in low-to-high order.
/// So, for example, if the documentation says the stack contains "(K, L)", then
/// an entity of kind L is on the top of the stack, with an entity of kind K
/// under it.  This low-to-high order is used when describing pushes and pops
/// too, so, for example a method documented with "pushes (K, L)" pushes K
/// first, then L, whereas a method documented with "pops (K, L)" pops L first,
/// then K.
///
/// In the paragraph above, "K" and "L" are just variables for illustrating the
/// conventions.  The actual kinds used by the analyzer are concepts from the
/// language itself such as "Statement", "Expression", "Pattern", etc.  See the
/// `Kind` enum in `test/mini_ir.dart` for a discussion of all possible kinds of
/// stack entries.
///
/// If multiple stack entries share a kind, we will sometimes add a name to
/// clarify which stack entry is which, e.g. analyzeIfStatement pushes
/// "(Expression condition, Statement ifTrue, Statement ifFalse)".
///
/// We'll also use the convention that "n * K" represents n consecutive entities
/// in the stack, each with kind K.
///
/// The kind associated with all pushes and pops is statically known (and
/// documented, and unit tested), and entities never change from one kind to
/// another.  This fact gives the client considerable freedom in how to actually
/// represent the stack in practice; for example, they might choose to ignore
/// some kinds entirely, or represent certain kinds with a block of multiple
/// stack entries instead of just one.  Or they might choose to multiple stacks,
/// one for each kind.  It's also possible that some clients won't need to keep
/// a stack at all.
///
/// Reasons a client might want to actually have a stack include:
/// - Constructing a lowered intermediate representation of the code as a side
///   effect of analysis,
/// - Building up a symbolic representation of the program's runtime behavior,
/// - Or keeping track of AST nodes that need to be replaced (e.g. replacing an
///   `integer literal` node with a `double literal` node when int->double
///   conversion happens).
///
/// The unit tests in the `_fe_analyzer_shared` package associate a simple
/// intermediate representation with each stack entry, and also record the kind
/// of each entry in order to verify that when an entity is popped, it has the
/// expected kind.
mixin TypeAnalyzer<
    Node extends Object,
    Statement extends Node,
    Expression extends Node,
    Variable extends Object,
    Type extends Object,
    Pattern extends Node,
    Error> {
  /// Returns the type `bool`.
  Type get boolType;

  /// Returns the type `double`.
  Type get doubleType;

  /// Returns the type `dynamic`.
  Type get dynamicType;

  TypeAnalyzerErrors<Node, Statement, Expression, Variable, Type, Pattern,
      Error> get errors;

  /// Returns the type used by the client in the case of errors.
  Type get errorType;

  /// Returns the client's [FlowAnalysis] object.
  FlowAnalysis<Node, Statement, Expression, Variable, Type> get flow;

  /// Returns the type `int`.
  Type get intType;

  /// Returns the type `Object?`.
  Type get objectQuestionType;

  /// The [Operations], used to access types, check subtyping, and query
  /// variable types.
  Operations<Variable, Type> get operations;

  /// Options affecting the behavior of [TypeAnalyzer].
  TypeAnalyzerOptions get options;

  /// Returns the unknown type context (`?`) used in type inference.
  Type get unknownType;

  /// Analyzes a non-wildcard variable pattern appearing in an assignment
  /// context.  [node] is the pattern itself, and [variable] is the variable
  /// being referenced.
  ///
  /// Returns an [AssignedVariablePatternResult] with information about reported
  /// errors.
  ///
  /// See [dispatchPattern] for the meaning of [context].
  ///
  /// For wildcard patterns in an assignment context,
  /// [analyzeDeclaredVariablePattern] should be used instead.
  ///
  /// Stack effect: none.
  AssignedVariablePatternResult<Error> analyzeAssignedVariablePattern(
      MatchContext<Node, Expression, Pattern, Type, Variable> context,
      Pattern node,
      Variable variable) {
    Error? duplicateAssignmentPatternVariableError;
    Map<Variable, Pattern>? assignedVariables = context.assignedVariables;
    if (assignedVariables != null) {
      Pattern? original = assignedVariables[variable];
      if (original == null) {
        assignedVariables[variable] = node;
      } else {
        duplicateAssignmentPatternVariableError =
            errors.duplicateAssignmentPatternVariable(
          variable: variable,
          original: original,
          duplicate: node,
        );
      }
    }

    Type variableDeclaredType = operations.variableType(variable);
    Node? irrefutableContext = context.irrefutableContext;
    assert(irrefutableContext != null,
        'Assigned variables must only appear in irrefutable pattern contexts');
    Type matchedType = flow.getMatchedValueType();
    Error? patternTypeMismatchInIrrefutableContextError;
    if (irrefutableContext != null &&
        !operations.isDynamic(matchedType) &&
        !operations.isSubtypeOf(matchedType, variableDeclaredType)) {
      patternTypeMismatchInIrrefutableContextError =
          errors.patternTypeMismatchInIrrefutableContext(
              pattern: node,
              context: irrefutableContext,
              matchedType: matchedType,
              requiredType: variableDeclaredType);
    }
    flow.promoteForPattern(
        matchedType: matchedType, knownType: variableDeclaredType);
    flow.assignedVariablePattern(node, variable, matchedType);
    return new AssignedVariablePatternResult(
        duplicateAssignmentPatternVariableError:
            duplicateAssignmentPatternVariableError,
        patternTypeMismatchInIrrefutableContextError:
            patternTypeMismatchInIrrefutableContextError);
  }

  /// Computes the type schema for a variable pattern appearing in an assignment
  /// context.  [variable] is the variable being referenced.
  Type analyzeAssignedVariablePatternSchema(Variable variable) =>
      flow.promotedType(variable) ?? operations.variableType(variable);

  /// Analyzes a cast pattern.  [innerPattern] is the sub-pattern] and
  /// [requiredType] is the type to cast to.
  ///
  /// See [dispatchPattern] for the meaning of [context].
  ///
  /// Stack effect: pushes (Pattern innerPattern).
  void analyzeCastPattern({
    required MatchContext<Node, Expression, Pattern, Type, Variable> context,
    required Pattern pattern,
    required Pattern innerPattern,
    required Type requiredType,
  }) {
    Type matchedValueType = flow.getMatchedValueType();
    bool matchedTypeIsSubtypeOfRequired = flow.promoteForPattern(
        matchedType: matchedValueType,
        knownType: requiredType,
        matchFailsIfWrongType: false);
    if (matchedTypeIsSubtypeOfRequired) {
      errors.matchedTypeIsSubtypeOfRequired(
        pattern: pattern,
        matchedType: matchedValueType,
        requiredType: requiredType,
      );
    }
    // Note: although technically the inner pattern match of a cast-pattern
    // operates on the same value as the cast pattern does, we analyze it as
    // though it's a different value; this ensures that (a) the matched value
    // type when matching the inner pattern is precisely the cast type, and (b)
    // promotions triggered by the inner pattern have no effect outside the
    // cast.
    flow.pushSubpattern(requiredType);
    dispatchPattern(context.withUnnecessaryWildcardKind(null), innerPattern);
    // Stack: (Pattern)
    flow.popSubpattern();
  }

  /// Computes the type schema for a cast pattern.
  ///
  /// Stack effect: none.
  Type analyzeCastPatternSchema() => objectQuestionType;

  /// Analyzes a constant pattern.  [node] is the pattern itself, and
  /// [expression] is the constant expression.  Depending on the client's
  /// representation, [node] and [expression] might or might not be identical.
  ///
  /// See [dispatchPattern] for the meaning of [context].
  ///
  /// Returns a [ConstantPatternResult] with the static type of [expression]
  /// and information about reported errors.
  ///
  /// Stack effect: pushes (Expression).
  ConstantPatternResult<Type, Error> analyzeConstantPattern(
      MatchContext<Node, Expression, Pattern, Type, Variable> context,
      Node node,
      Expression expression) {
    // Stack: ()
    Node? irrefutableContext = context.irrefutableContext;
    Error? refutablePatternInIrrefutableContextError;
    if (irrefutableContext != null) {
      refutablePatternInIrrefutableContextError =
          errors.refutablePatternInIrrefutableContext(
              pattern: node, context: irrefutableContext);
    }
    Type matchedType = flow.getMatchedValueType();
    Type expressionType = analyzeExpression(expression, matchedType);
    flow.constantPattern_end(expression, expressionType,
        patternsEnabled: options.patternsEnabled);
    // Stack: (Expression)
    Error? caseExpressionTypeMismatchError;
    if (!options.patternsEnabled) {
      Expression? switchScrutinee = context.switchScrutinee;
      if (switchScrutinee != null) {
        bool nullSafetyEnabled = options.nullSafetyEnabled;
        bool matches = nullSafetyEnabled
            ? operations.isSubtypeOf(expressionType, matchedType)
            : operations.isAssignableTo(expressionType, matchedType);
        if (!matches) {
          caseExpressionTypeMismatchError = errors.caseExpressionTypeMismatch(
              caseExpression: expression,
              scrutinee: switchScrutinee,
              caseExpressionType: expressionType,
              scrutineeType: matchedType,
              nullSafetyEnabled: nullSafetyEnabled);
        }
      }
    }
    return new ConstantPatternResult(
        expressionType: expressionType,
        refutablePatternInIrrefutableContextError:
            refutablePatternInIrrefutableContextError,
        caseExpressionTypeMismatchError: caseExpressionTypeMismatchError);
  }

  /// Computes the type schema for a constant pattern.
  ///
  /// Stack effect: none.
  Type analyzeConstantPatternSchema() {
    // Constant patterns are only allowed in refutable contexts, and refutable
    // contexts don't propagate a type schema into the scrutinee.  So this
    // code path is only reachable if the user's code contains errors.
    errors.assertInErrorRecovery();
    return unknownType;
  }

  /// Analyzes a variable pattern in a non-assignment context.  [node] is the
  /// pattern itself, [variable] is the variable, [declaredType] is the
  /// explicitly declared type (if present).  [variableName] is the name of the
  /// variable; this is used to match up corresponding variables in the
  /// different branches of logical-or patterns, as well as different switch
  /// cases that share a body.
  ///
  /// See [dispatchPattern] for the meaning of [context].
  ///
  /// Returns a [DeclaredVariablePatternResult] with the static type of the
  /// variable (possibly inferred) and information about reported errors.
  ///
  /// Stack effect: none.
  DeclaredVariablePatternResult<Type, Error> analyzeDeclaredVariablePattern(
    MatchContext<Node, Expression, Pattern, Type, Variable> context,
    Pattern node,
    Variable variable,
    String variableName,
    Type? declaredType,
  ) {
    Type matchedType = flow.getMatchedValueType();
    Type staticType =
        declaredType ?? variableTypeFromInitializerType(matchedType);
    Node? irrefutableContext = context.irrefutableContext;
    Error? patternTypeMismatchInIrrefutableContextError;
    if (irrefutableContext != null &&
        !operations.isDynamic(matchedType) &&
        !operations.isSubtypeOf(matchedType, staticType)) {
      patternTypeMismatchInIrrefutableContextError =
          errors.patternTypeMismatchInIrrefutableContext(
              pattern: node,
              context: irrefutableContext,
              matchedType: matchedType,
              requiredType: staticType);
    }
    flow.promoteForPattern(matchedType: matchedType, knownType: staticType);
    // The promotion may have made the matched type even more specific than
    // either `matchedType` or `staticType`, so fetch it again and use that
    // in the call to `declaredVariablePattern` below.
    matchedType = flow.getMatchedValueType();
    bool isImplicitlyTyped = declaredType == null;
    // TODO(paulberry): are we handling _isFinal correctly?
    int promotionKey = context.patternVariablePromotionKeys[variableName] =
        flow.declaredVariablePattern(
            matchedType: matchedType,
            staticType: staticType,
            isFinal: context.isFinal || isVariableFinal(variable),
            isLate: context.isLate,
            isImplicitlyTyped: isImplicitlyTyped);
    setVariableType(variable, staticType);
    (context.componentVariables[variableName] ??= []).add(variable);
    flow.assignMatchedPatternVariable(variable, promotionKey);
    return new DeclaredVariablePatternResult(
        staticType: staticType,
        patternTypeMismatchInIrrefutableContextError:
            patternTypeMismatchInIrrefutableContextError);
  }

  /// Computes the type schema for a variable pattern in a non-assignment
  /// context (or a wildcard pattern).  [declaredType] is the explicitly
  /// declared type (if present).
  ///
  /// Stack effect: none.
  Type analyzeDeclaredVariablePatternSchema(Type? declaredType) {
    return declaredType ?? unknownType;
  }

  /// Analyzes an expression.  [node] is the expression to analyze, and
  /// [context] is the type schema which should be used for type inference.
  ///
  /// Stack effect: pushes (Expression).
  Type analyzeExpression(Expression node, Type? context) {
    // Stack: ()
    if (context == null || operations.isDynamic(context)) {
      context = unknownType;
    }
    ExpressionTypeAnalysisResult<Type> result =
        dispatchExpression(node, context);
    // Stack: (Expression)
    if (operations.isNever(result.provisionalType)) {
      flow.handleExit();
    }
    return result.resolveShorting();
  }

  /// Analyzes a collection element of the form
  /// `if (expression case pattern) ifTrue` or
  /// `if (expression case pattern) ifTrue else ifFalse`.
  ///
  /// [node] should be the AST node for the entire element, [expression] for
  /// the expression, [pattern] for the pattern to match, [ifTrue] for the
  /// "then" branch, and [ifFalse] for the "else" branch (if present).
  ///
  /// [variables] should be a map from variable name to the variable the client
  /// wishes to use to represent that variable.  This is used to join together
  /// variables that appear in different branches of logical-or patterns.
  ///
  /// Returns a [IfCaseStatementResult] with the static type of [expression] and
  /// information about reported errors.
  ///
  /// Stack effect: pushes (Expression scrutinee, Pattern, Expression guard,
  /// CollectionElement ifTrue, CollectionElement ifFalse).  If there is no
  /// `else` clause, the representation for `ifFalse` will be pushed by
  /// [handleNoCollectionElement].  If there is no guard, the representation
  /// for `guard` will be pushed by [handleNoGuard].
  IfCaseStatementResult<Type, Error> analyzeIfCaseElement({
    required Node node,
    required Expression expression,
    required Pattern pattern,
    required Map<String, Variable> variables,
    required Expression? guard,
    required Node ifTrue,
    required Node? ifFalse,
    required Object? context,
  }) {
    // Stack: ()
    flow.ifCaseStatement_begin();
    Type initializerType = analyzeExpression(expression, unknownType);
    flow.ifCaseStatement_afterExpression(expression, initializerType);
    // Stack: (Expression)
    Map<String, List<Variable>> componentVariables = {};
    Map<String, int> patternVariablePromotionKeys = {};
    // TODO(paulberry): rework handling of isFinal
    dispatchPattern(
      new MatchContext<Node, Expression, Pattern, Type, Variable>(
        isFinal: false,
        componentVariables: componentVariables,
        patternVariablePromotionKeys: patternVariablePromotionKeys,
      ),
      pattern,
    );
    // Stack: (Expression, Pattern)
    _finishJoinedPatternVariables(
        variables, componentVariables, patternVariablePromotionKeys,
        location: JoinedPatternVariableLocation.singlePattern);
    Error? nonBooleanGuardError;
    Type? guardType;
    if (guard != null) {
      guardType = analyzeExpression(guard, boolType);
      nonBooleanGuardError = _checkGuardType(guard, guardType);
    } else {
      handleNoGuard(node, 0);
    }
    // Stack: (Expression, Pattern, Guard)
    flow.ifCaseStatement_thenBegin(guard);
    _analyzeIfElementCommon(node, ifTrue, ifFalse, context);
    return new IfCaseStatementResult(
        matchedExpressionType: initializerType,
        nonBooleanGuardError: nonBooleanGuardError,
        guardType: guardType);
  }

  /// Analyzes a statement of the form `if (expression case pattern) ifTrue` or
  /// `if (expression case pattern) ifTrue else ifFalse`.
  ///
  /// [node] should be the AST node for the entire statement, [expression] for
  /// the expression, [pattern] for the pattern to match, [ifTrue] for the
  /// "then" branch, and [ifFalse] for the "else" branch (if present).
  ///
  /// Returns a [IfCaseStatementResult] with the static type of [expression] and
  /// information about reported errors.
  ///
  /// Stack effect: pushes (Expression scrutinee, Pattern, Expression guard,
  /// Statement ifTrue, Statement ifFalse).  If there is no `else` clause, the
  /// representation for `ifFalse` will be pushed by [handleNoStatement].  If
  /// there is no guard, the representation for `guard` will be pushed by
  /// [handleNoGuard].
  IfCaseStatementResult<Type, Error> analyzeIfCaseStatement(
    Statement node,
    Expression expression,
    Pattern pattern,
    Expression? guard,
    Statement ifTrue,
    Statement? ifFalse,
    Map<String, Variable> variables,
  ) {
    // Stack: ()
    flow.ifCaseStatement_begin();
    Type initializerType = analyzeExpression(expression, unknownType);
    flow.ifCaseStatement_afterExpression(expression, initializerType);
    // Stack: (Expression)
    Map<String, List<Variable>> componentVariables = {};
    Map<String, int> patternVariablePromotionKeys = {};
    // TODO(paulberry): rework handling of isFinal
    dispatchPattern(
      new MatchContext<Node, Expression, Pattern, Type, Variable>(
        isFinal: false,
        componentVariables: componentVariables,
        patternVariablePromotionKeys: patternVariablePromotionKeys,
      ),
      pattern,
    );

    _finishJoinedPatternVariables(
      variables,
      componentVariables,
      patternVariablePromotionKeys,
      location: JoinedPatternVariableLocation.singlePattern,
    );

    handle_ifCaseStatement_afterPattern(node: node);
    // Stack: (Expression, Pattern)
    Error? nonBooleanGuardError;
    Type? guardType;
    if (guard != null) {
      guardType = analyzeExpression(guard, boolType);
      nonBooleanGuardError = _checkGuardType(guard, guardType);
    } else {
      handleNoGuard(node, 0);
    }
    // Stack: (Expression, Pattern, Guard)
    flow.ifCaseStatement_thenBegin(guard);
    _analyzeIfCommon(node, ifTrue, ifFalse);
    return new IfCaseStatementResult(
        matchedExpressionType: initializerType,
        nonBooleanGuardError: nonBooleanGuardError,
        guardType: guardType);
  }

  /// Analyzes a collection element of the form `if (condition) ifTrue` or
  /// `if (condition) ifTrue else ifFalse`.
  ///
  /// [node] should be the AST node for the entire element, [condition] for
  /// the condition expression, [ifTrue] for the "then" branch, and [ifFalse]
  /// for the "else" branch (if present).
  ///
  /// Stack effect: pushes (Expression condition, CollectionElement ifTrue,
  /// CollectionElement ifFalse).  Note that if there is no `else` clause, the
  /// representation for `ifFalse` will be pushed by
  /// [handleNoCollectionElement].
  void analyzeIfElement({
    required Node node,
    required Expression condition,
    required Node ifTrue,
    required Node? ifFalse,
    required Object? context,
  }) {
    // Stack: ()
    flow.ifStatement_conditionBegin();
    analyzeExpression(condition, boolType);
    handle_ifElement_conditionEnd(node);
    // Stack: (Expression condition)
    flow.ifStatement_thenBegin(condition, node);
    _analyzeIfElementCommon(node, ifTrue, ifFalse, context);
  }

  /// Analyzes a statement of the form `if (condition) ifTrue` or
  /// `if (condition) ifTrue else ifFalse`.
  ///
  /// [node] should be the AST node for the entire statement, [condition] for
  /// the condition expression, [ifTrue] for the "then" branch, and [ifFalse]
  /// for the "else" branch (if present).
  ///
  /// Stack effect: pushes (Expression condition, Statement ifTrue, Statement
  /// ifFalse).  Note that if there is no `else` clause, the representation for
  /// `ifFalse` will be pushed by [handleNoStatement].
  void analyzeIfStatement(Statement node, Expression condition,
      Statement ifTrue, Statement? ifFalse) {
    // Stack: ()
    flow.ifStatement_conditionBegin();
    analyzeExpression(condition, boolType);
    handle_ifStatement_conditionEnd(node);
    // Stack: (Expression condition)
    flow.ifStatement_thenBegin(condition, node);
    _analyzeIfCommon(node, ifTrue, ifFalse);
  }

  /// Analyzes an integer literal, given the type context [context].
  ///
  /// Stack effect: none.
  IntTypeAnalysisResult<Type> analyzeIntLiteral(Type context) {
    bool convertToDouble = !operations.isSubtypeOf(intType, context) &&
        operations.isSubtypeOf(doubleType, context);
    Type type = convertToDouble ? doubleType : intType;
    return new IntTypeAnalysisResult<Type>(
        type: type, convertedToDouble: convertToDouble);
  }

  /// Analyzes a list pattern.  [node] is the pattern itself, [elementType] is
  /// the list element type (if explicitly supplied), and [elements] is the
  /// list of subpatterns.
  ///
  /// Returns a [ListPatternResult] with the required type and information about
  /// reported errors.
  ///
  /// See [dispatchPattern] for the meaning of [context].
  ///
  /// Stack effect: pushes (n * Pattern) where n = elements.length.
  ListPatternResult<Type, Error> analyzeListPattern(
      MatchContext<Node, Expression, Pattern, Type, Variable> context,
      Pattern node,
      {Type? elementType,
      required List<Node> elements}) {
    Type valueType;
    Type matchedType = flow.getMatchedValueType();
    if (elementType != null) {
      valueType = elementType;
    } else {
      Type? listElementType = operations.matchListType(matchedType);
      if (listElementType != null) {
        valueType = listElementType;
      } else if (operations.isDynamic(matchedType)) {
        valueType = dynamicType;
      } else {
        valueType = objectQuestionType;
      }
    }
    Type requiredType = listType(valueType);
    flow.promoteForPattern(
        matchedType: matchedType,
        knownType: requiredType,
        matchMayFailEvenIfCorrectType: true);
    // Stack: ()
    Node? previousRestPattern;
    Map<int, Error>? duplicateRestPatternErrors;
    for (int i = 0; i < elements.length; i++) {
      Node element = elements[i];
      if (isRestPatternElement(element)) {
        if (previousRestPattern != null) {
          (duplicateRestPatternErrors ??= {})[i] = errors.duplicateRestPattern(
            mapOrListPattern: node,
            original: previousRestPattern,
            duplicate: element,
          );
        }
        previousRestPattern = element;
        Pattern? subPattern = getRestPatternElementPattern(element);
        if (subPattern != null) {
          Type subPatternMatchedType = requiredType;
          flow.pushSubpattern(subPatternMatchedType);
          dispatchPattern(
              context.withUnnecessaryWildcardKind(null), subPattern);
          flow.popSubpattern();
        }
        handleListPatternRestElement(node, element);
      } else {
        flow.pushSubpattern(valueType);
        dispatchPattern(context.withUnnecessaryWildcardKind(null), element);
        flow.popSubpattern();
      }
    }
    // Stack: (n * Pattern) where n = elements.length
    Node? irrefutableContext = context.irrefutableContext;
    Error? patternTypeMismatchInIrrefutableContextError;
    if (irrefutableContext != null &&
        !operations.isAssignableTo(matchedType, requiredType)) {
      patternTypeMismatchInIrrefutableContextError =
          errors.patternTypeMismatchInIrrefutableContext(
              pattern: node,
              context: irrefutableContext,
              matchedType: matchedType,
              requiredType: requiredType);
    }
    return new ListPatternResult(
        requiredType: requiredType,
        duplicateRestPatternErrors: duplicateRestPatternErrors,
        patternTypeMismatchInIrrefutableContextError:
            patternTypeMismatchInIrrefutableContextError);
  }

  /// Computes the type schema for a list pattern.  [elementType] is the list
  /// element type (if explicitly supplied), and [elements] is the list of
  /// subpatterns.
  ///
  /// Stack effect: none.
  Type analyzeListPatternSchema({
    required Type? elementType,
    required List<Node> elements,
  }) {
    if (elementType != null) {
      return listType(elementType);
    }

    if (elements.isEmpty) {
      return listType(unknownType);
    }

    Type? currentGLB;
    for (Node element in elements) {
      Type? typeToAdd;
      if (isRestPatternElement(element)) {
        Pattern? subPattern = getRestPatternElementPattern(element);
        if (subPattern != null) {
          Type subPatternType = dispatchPatternSchema(subPattern);
          typeToAdd = operations.matchIterableType(subPatternType);
        }
      } else {
        typeToAdd = dispatchPatternSchema(element);
      }
      if (typeToAdd != null) {
        if (currentGLB == null) {
          currentGLB = typeToAdd;
        } else {
          currentGLB = operations.glb(currentGLB, typeToAdd);
        }
      }
    }
    currentGLB ??= unknownType;
    return listType(currentGLB);
  }

  /// Analyzes a logical-and pattern.  [node] is the pattern itself, and [lhs]
  /// and [rhs] are the left and right sides of the `&&` operator.
  ///
  /// See [dispatchPattern] for the meaning of [context].
  ///
  /// Stack effect: pushes (Pattern left, Pattern right)
  void analyzeLogicalAndPattern(
      MatchContext<Node, Expression, Pattern, Type, Variable> context,
      Pattern node,
      Node lhs,
      Node rhs) {
    // Stack: ()
    dispatchPattern(
      context.withUnnecessaryWildcardKind(
        UnnecessaryWildcardKind.logicalAndPatternOperand,
      ),
      lhs,
    );
    // Stack: (Pattern left)
    dispatchPattern(
      context.withUnnecessaryWildcardKind(
        UnnecessaryWildcardKind.logicalAndPatternOperand,
      ),
      rhs,
    );
    // Stack: (Pattern left, Pattern right)
  }

  /// Computes the type schema for a logical-and pattern.  [lhs] and [rhs] are
  /// the left and right sides of the `&&` operator.
  ///
  /// Stack effect: none.
  Type analyzeLogicalAndPatternSchema(Node lhs, Node rhs) {
    return operations.glb(
        dispatchPatternSchema(lhs), dispatchPatternSchema(rhs));
  }

  /// Analyzes a logical-or pattern.  [node] is the pattern itself, and [lhs]
  /// and [rhs] are the left and right sides of the `||` operator.
  ///
  /// Returns a [LogicalOrPatternResult] with information about reported errors.
  ///
  /// See [dispatchPattern] for the meaning of [context].
  ///
  /// Stack effect: pushes (Pattern left, Pattern right)
  LogicalOrPatternResult<Error> analyzeLogicalOrPattern(
      MatchContext<Node, Expression, Pattern, Type, Variable> context,
      Pattern node,
      Node lhs,
      Node rhs) {
    Node? irrefutableContext = context.irrefutableContext;
    Error? refutablePatternInIrrefutableContextError;
    if (irrefutableContext != null) {
      refutablePatternInIrrefutableContextError =
          errors.refutablePatternInIrrefutableContext(
              pattern: node, context: irrefutableContext);
      // Avoid cascading errors
      context = context.makeRefutable();
    }
    // Stack: ()
    flow.logicalOrPattern_begin();
    Map<String, int> leftPromotionKeys = {};
    dispatchPattern(
      context
          .withPromotionKeys(leftPromotionKeys)
          .withUnnecessaryWildcardKind(null),
      lhs,
    );
    // Stack: (Pattern left)
    // We'll use the promotion keys allocated during processing of the LHS as
    // the merged keys.
    for (MapEntry<String, int> entry in leftPromotionKeys.entries) {
      String variableName = entry.key;
      int promotionKey = entry.value;
      assert(!context.patternVariablePromotionKeys.containsKey(variableName));
      context.patternVariablePromotionKeys[variableName] = promotionKey;
    }
    flow.logicalOrPattern_afterLhs();
    handle_logicalOrPattern_afterLhs(node);
    Map<String, int> rightPromotionKeys = {};
    dispatchPattern(
      context
          .withPromotionKeys(rightPromotionKeys)
          .withUnnecessaryWildcardKind(null),
      rhs,
    );
    // Stack: (Pattern left, Pattern right)
    for (MapEntry<String, int> entry in rightPromotionKeys.entries) {
      String variableName = entry.key;
      int rightPromotionKey = entry.value;
      int? mergedPromotionKey = leftPromotionKeys[variableName];
      if (mergedPromotionKey == null) {
        // No matching variable on the LHS.  This is an error condition (which
        // has already been reported by VariableBinder).  For error recovery,
        // we still need to add the variable to
        // context.patternVariablePromotionKeys so that later analysis still
        // accounts for the presence of this variable.  So we just use the
        // promotion key from the RHS as the merged key.
        mergedPromotionKey = rightPromotionKey;
        assert(!context.patternVariablePromotionKeys.containsKey(variableName));
        context.patternVariablePromotionKeys[variableName] = mergedPromotionKey;
      } else {
        // Copy the promotion data over to the merged key.
        flow.copyPromotionData(
            sourceKey: rightPromotionKey, destinationKey: mergedPromotionKey);
      }
    }
    // Since the promotion data is now all stored in the merged keys in both
    // flow control branches, the normal join process will combine promotions
    // accordingly.
    flow.logicalOrPattern_end();
    return new LogicalOrPatternResult(
        refutablePatternInIrrefutableContextError:
            refutablePatternInIrrefutableContextError);
  }

  /// Computes the type schema for a logical-or pattern.  [lhs] and [rhs] are
  /// the left and right sides of the `|` or `&` operator.
  ///
  /// Stack effect: none.
  Type analyzeLogicalOrPatternSchema(Node lhs, Node rhs) {
    // Logical-or patterns are only allowed in refutable contexts, and
    // refutable contexts don't propagate a type schema into the scrutinee.
    // So this code path is only reachable if the user's code contains errors.
    errors.assertInErrorRecovery();
    return unknownType;
  }

  /// Analyzes a map pattern.  [node] is the pattern itself, [typeArguments]
  /// contain explicit type arguments (if specified), and [elements] is the
  /// list of subpatterns.
  ///
  /// Returns a [MapPatternResult] with the required type and information about
  /// reported errors.
  ///
  /// See [dispatchPattern] for the meaning of [context].
  ///
  /// Stack effect: pushes (n * MapPatternElement) where n = elements.length.
  MapPatternResult<Type, Error> analyzeMapPattern(
    MatchContext<Node, Expression, Pattern, Type, Variable> context,
    Pattern node, {
    required MapPatternTypeArguments<Type>? typeArguments,
    required List<Node> elements,
  }) {
    Type keyType;
    Type valueType;
    Type keyContext;
    Type matchedType = flow.getMatchedValueType();
    if (typeArguments != null) {
      keyType = typeArguments.keyType;
      valueType = typeArguments.valueType;
      keyContext = keyType;
    } else {
      typeArguments = operations.matchMapType(matchedType);
      if (typeArguments != null) {
        keyType = typeArguments.keyType;
        valueType = typeArguments.valueType;
        keyContext = keyType;
      } else if (operations.isDynamic(matchedType)) {
        keyType = dynamicType;
        valueType = dynamicType;
        keyContext = unknownType;
      } else {
        keyType = objectQuestionType;
        valueType = objectQuestionType;
        keyContext = unknownType;
      }
    }
    Type requiredType = mapType(
      keyType: keyType,
      valueType: valueType,
    );
    flow.promoteForPattern(
        matchedType: matchedType,
        knownType: requiredType,
        matchMayFailEvenIfCorrectType: true);
    // Stack: ()

    bool hasDuplicateRestPatternReported = false;
    Node? previousRestPattern;
    Map<int, Error>? duplicateRestPatternErrors;
    for (int i = 0; i < elements.length; i++) {
      Node element = elements[i];
      if (isRestPatternElement(element)) {
        if (previousRestPattern != null) {
          (duplicateRestPatternErrors ??= {})[i] = errors.duplicateRestPattern(
            mapOrListPattern: node,
            original: previousRestPattern,
            duplicate: element,
          );
          hasDuplicateRestPatternReported = true;
        }
        previousRestPattern = element;
      }
    }

    for (int i = 0; i < elements.length; i++) {
      Node element = elements[i];
      MapPatternEntry<Expression, Pattern>? entry = getMapPatternEntry(element);
      if (entry != null) {
        Type keyType = analyzeExpression(entry.key, keyContext);
        flow.pushSubpattern(valueType);
        dispatchPattern(
          context.withUnnecessaryWildcardKind(null),
          entry.value,
        );
        handleMapPatternEntry(node, element, keyType);
        flow.popSubpattern();
      } else {
        assert(isRestPatternElement(element));
        if (!hasDuplicateRestPatternReported) {
          if (i != elements.length - 1) {
            errors.restPatternNotLastInMap(node: node, element: element);
          }
        }
        Pattern? subPattern = getRestPatternElementPattern(element);
        if (subPattern != null) {
          errors.restPatternWithSubPatternInMap(node: node, element: element);
          flow.pushSubpattern(dynamicType);
          dispatchPattern(
            context.withUnnecessaryWildcardKind(null),
            subPattern,
          );
          flow.popSubpattern();
        }
        handleMapPatternRestElement(node, element);
      }
    }
    // Stack: (n * MapPatternElement) where n = elements.length
    Node? irrefutableContext = context.irrefutableContext;
    Error? patternTypeMismatchInIrrefutableContextError;
    if (irrefutableContext != null &&
        !operations.isAssignableTo(matchedType, requiredType)) {
      patternTypeMismatchInIrrefutableContextError =
          errors.patternTypeMismatchInIrrefutableContext(
        pattern: node,
        context: irrefutableContext,
        matchedType: matchedType,
        requiredType: requiredType,
      );
    }
    return new MapPatternResult(
        requiredType: requiredType,
        duplicateRestPatternErrors: duplicateRestPatternErrors,
        patternTypeMismatchInIrrefutableContextError:
            patternTypeMismatchInIrrefutableContextError);
  }

  /// Computes the type schema for a map pattern.  [typeArguments] contain
  /// explicit type arguments (if specified), and [elements] is the list of
  /// subpatterns.
  ///
  /// Stack effect: none.
  Type analyzeMapPatternSchema({
    required MapPatternTypeArguments<Type>? typeArguments,
    required List<Node> elements,
  }) {
    if (typeArguments != null) {
      return mapType(
        keyType: typeArguments.keyType,
        valueType: typeArguments.valueType,
      );
    }

    Type? valueType;
    for (Node element in elements) {
      MapPatternEntry<Expression, Pattern>? entry = getMapPatternEntry(element);
      if (entry != null) {
        Type entryValueType = dispatchPatternSchema(entry.value);
        if (valueType == null) {
          valueType = entryValueType;
        } else {
          valueType = operations.glb(valueType, entryValueType);
        }
      }
    }
    return mapType(
      keyType: unknownType,
      valueType: valueType ?? unknownType,
    );
  }

  /// Analyzes a null-check or null-assert pattern.  [node] is the pattern
  /// itself, [innerPattern] is the sub-pattern, and [isAssert] indicates
  /// whether this is a null-check or a null-assert pattern.
  ///
  /// Returns a [NullCheckOrAssertPatternResult] with information about
  /// reported errors.
  ///
  /// See [dispatchPattern] for the meaning of [context].
  ///
  /// Stack effect: pushes (Pattern innerPattern).
  NullCheckOrAssertPatternResult<Error> analyzeNullCheckOrAssertPattern(
      MatchContext<Node, Expression, Pattern, Type, Variable> context,
      Pattern node,
      Pattern innerPattern,
      {required bool isAssert}) {
    // Stack: ()
    Error? refutablePatternInIrrefutableContextError;
    Error? matchedTypeIsStrictlyNonNullableError;
    Node? irrefutableContext = context.irrefutableContext;
    bool matchedTypeIsStrictlyNonNullable =
        flow.nullCheckOrAssertPattern_begin(isAssert: isAssert);
    if (irrefutableContext != null && !isAssert) {
      refutablePatternInIrrefutableContextError =
          errors.refutablePatternInIrrefutableContext(
              pattern: node, context: irrefutableContext);
      // Avoid cascading errors
      context = context.makeRefutable();
    } else if (matchedTypeIsStrictlyNonNullable) {
      matchedTypeIsStrictlyNonNullableError =
          errors.matchedTypeIsStrictlyNonNullable(
        pattern: node,
        matchedType: flow.getMatchedValueType(),
      );
    }
    dispatchPattern(
      context.withUnnecessaryWildcardKind(null),
      innerPattern,
    );
    // Stack: (Pattern)
    flow.nullCheckOrAssertPattern_end();

    return new NullCheckOrAssertPatternResult(
        refutablePatternInIrrefutableContextError:
            refutablePatternInIrrefutableContextError,
        matchedTypeIsStrictlyNonNullableError:
            matchedTypeIsStrictlyNonNullableError);
  }

  /// Computes the type schema for a null-check or null-assert pattern.
  /// [innerPattern] is the sub-pattern and [isAssert] indicates whether this is
  /// a null-check or a null-assert pattern.
  ///
  /// Stack effect: none.
  Type analyzeNullCheckOrAssertPatternSchema(Pattern innerPattern,
      {required bool isAssert}) {
    if (isAssert) {
      return operations.makeNullable(dispatchPatternSchema(innerPattern));
    } else {
      // Null-check patterns are only allowed in refutable contexts, and
      // refutable contexts don't propagate a type schema into the scrutinee.
      // So this code path is only reachable if the user's code contains errors.
      errors.assertInErrorRecovery();
      return unknownType;
    }
  }

  /// Analyzes an object pattern.  [node] is the pattern itself, and [fields]
  /// is the list of subpatterns.  The [requiredType] must be not `null` in
  /// irrefutable contexts, but can be `null` in refutable contexts, then
  /// [downwardInferObjectPatternRequiredType] is invoked to infer the type.
  ///
  /// Returns a [ObjectPatternResult] with the required type and information
  /// about reported errors.
  ///
  /// See [dispatchPattern] for the meaning of [context].
  ///
  /// Stack effect: pushes (n * Pattern) where n = fields.length.
  ObjectPatternResult<Type, Error> analyzeObjectPattern(
    MatchContext<Node, Expression, Pattern, Type, Variable> context,
    Pattern node, {
    required List<RecordPatternField<Node, Pattern>> fields,
  }) {
    Map<int, Error>? duplicateRecordPatternFieldErrors =
        _reportDuplicateRecordPatternFields(node, fields);

    Type matchedType = flow.getMatchedValueType();
    Type requiredType = downwardInferObjectPatternRequiredType(
      matchedType: matchedType,
      pattern: node,
    );
    flow.promoteForPattern(matchedType: matchedType, knownType: requiredType);

    // If the required type is `dynamic` or `Never`, then every getter is
    // treated as having the same type.
    Type? overridePropertyGetType;
    if (operations.isDynamic(requiredType) ||
        operations.isNever(requiredType)) {
      overridePropertyGetType = requiredType;
    }

    Node? irrefutableContext = context.irrefutableContext;
    Error? patternTypeMismatchInIrrefutableContextError;
    if (irrefutableContext != null &&
        !operations.isAssignableTo(matchedType, requiredType)) {
      patternTypeMismatchInIrrefutableContextError =
          errors.patternTypeMismatchInIrrefutableContext(
        pattern: node,
        context: irrefutableContext,
        matchedType: matchedType,
        requiredType: requiredType,
      );
    }

    // Stack: ()
    for (RecordPatternField<Node, Pattern> field in fields) {
      Type propertyType = overridePropertyGetType ??
          resolveObjectPatternPropertyGet(
            receiverType: requiredType,
            field: field,
          );
      flow.pushSubpattern(propertyType);
      dispatchPattern(
        context.withUnnecessaryWildcardKind(null),
        field.pattern,
      );
      flow.popSubpattern();
    }
    // Stack: (n * Pattern) where n = fields.length

    return new ObjectPatternResult(
        requiredType: requiredType,
        duplicateRecordPatternFieldErrors: duplicateRecordPatternFieldErrors,
        patternTypeMismatchInIrrefutableContextError:
            patternTypeMismatchInIrrefutableContextError);
  }

  /// Computes the type schema for an object pattern.  [type] is the type
  /// specified with the object name, and with the type arguments applied.
  ///
  /// Stack effect: none.
  Type analyzeObjectPatternSchema(Type type) {
    return type;
  }

  /// Analyzes a patternAssignment expression of the form `pattern = rhs`.
  ///
  /// [node] should be the AST node for the entire expression, [pattern] for
  /// the pattern, and [rhs] for the right hand side.
  ///
  /// Stack effect: pushes (Expression, Pattern).
  PatternAssignmentAnalysisResult<Type> analyzePatternAssignment(
      Expression node, Pattern pattern, Expression rhs) {
    // Stack: ()
    Type patternSchema = dispatchPatternSchema(pattern);
    Type rhsType = analyzeExpression(rhs, patternSchema);
    // Stack: (Expression)
    flow.patternAssignment_afterRhs(rhs, rhsType);
    Map<String, List<Variable>> componentVariables = {};
    Map<String, int> patternVariablePromotionKeys = {};
    dispatchPattern(
      new MatchContext<Node, Expression, Pattern, Type, Variable>(
        isFinal: false,
        irrefutableContext: node,
        assignedVariables: <Variable, Pattern>{},
        componentVariables: componentVariables,
        patternVariablePromotionKeys: patternVariablePromotionKeys,
      ),
      pattern,
    );
    if (componentVariables.isNotEmpty) {
      // Declared pattern variables should never appear in a pattern assignment
      // so this should never happen.
      errors.assertInErrorRecovery();
    }
    flow.patternAssignment_end();
    // Stack: (Expression, Pattern)
    return new PatternAssignmentAnalysisResult<Type>(
      patternSchema: patternSchema,
      type: rhsType,
    );
  }

  /// Analyzes a `pattern-for-in` statement or element.
  ///
  /// Statement:
  /// `for (<keyword> <pattern> in <expression>) <statement>`
  ///
  /// Element:
  /// `for (<keyword> <pattern> in <expression>) <body>`
  ///
  /// Stack effect: pushes (Expression, Pattern).
  ///
  /// Returns a [PatternForInResult] containing information on reported errors.
  PatternForInResult<Error> analyzePatternForIn({
    required Node node,
    required bool hasAwait,
    required Pattern pattern,
    required Expression expression,
    required void Function() dispatchBody,
  }) {
    // Stack: ()
    Type patternTypeSchema = dispatchPatternSchema(pattern);
    Type expressionTypeSchema = hasAwait
        ? streamType(patternTypeSchema)
        : iterableType(patternTypeSchema);
    Type expressionType = analyzeExpression(expression, expressionTypeSchema);
    // Stack: (Expression)

    Error? patternForInExpressionIsNotIterableError;
    Type? elementType = hasAwait
        ? operations.matchStreamType(expressionType)
        : operations.matchIterableType(expressionType);
    if (elementType == null) {
      if (operations.isDynamic(expressionType)) {
        elementType = dynamicType;
      } else {
        patternForInExpressionIsNotIterableError =
            errors.patternForInExpressionIsNotIterable(
          node: node,
          expression: expression,
          expressionType: expressionType,
        );
        elementType = dynamicType;
      }
    }
    flow.patternForIn_afterExpression(elementType);

    Map<String, List<Variable>> componentVariables = {};
    Map<String, int> patternVariablePromotionKeys = {};
    dispatchPattern(
      new MatchContext<Node, Expression, Pattern, Type, Variable>(
        isFinal: false,
        irrefutableContext: node,
        componentVariables: componentVariables,
        patternVariablePromotionKeys: patternVariablePromotionKeys,
      ),
      pattern,
    );
    // Stack: (Expression, Pattern)

    flow.forEach_bodyBegin(node);
    dispatchBody();
    flow.forEach_end();
    flow.patternForIn_end();

    return new PatternForInResult(
        patternForInExpressionIsNotIterableError:
            patternForInExpressionIsNotIterableError);
  }

  /// Analyzes a patternVariableDeclaration node of the form
  /// `var pattern = initializer` or `final pattern = initializer`.
  ///
  /// [node] should be the AST node for the entire declaration, [pattern] for
  /// the pattern, and [initializer] for the initializer.  [isFinal] and
  /// [isLate] indicate whether this is a final declaration and/or a late
  /// declaration, respectively.
  ///
  /// Note that the only kind of pattern allowed in a late declaration is a
  /// variable pattern; [TypeAnalyzerErrors.patternDoesNotAllowLate] will be
  /// reported if any other kind of pattern is used.
  ///
  /// Returns the type schema of the [pattern].
  ///
  /// Stack effect: pushes (Expression, Pattern).
  Type analyzePatternVariableDeclaration(
      Node node, Pattern pattern, Expression initializer,
      {required bool isFinal, required bool isLate}) {
    // Stack: ()
    if (isLate && !isVariablePattern(pattern)) {
      errors.patternDoesNotAllowLate(pattern: pattern);
    }
    if (isLate) {
      flow.lateInitializer_begin(node);
    }
    Type patternSchema = dispatchPatternSchema(pattern);
    Type initializerType = analyzeExpression(initializer, patternSchema);
    // Stack: (Expression)
    if (isLate) {
      flow.lateInitializer_end();
    }
    flow.patternVariableDeclaration_afterInitializer(
        initializer, initializerType);
    Map<String, List<Variable>> componentVariables = {};
    Map<String, int> patternVariablePromotionKeys = {};
    dispatchPattern(
      new MatchContext<Node, Expression, Pattern, Type, Variable>(
        isFinal: isFinal,
        isLate: isLate,
        irrefutableContext: node,
        componentVariables: componentVariables,
        patternVariablePromotionKeys: patternVariablePromotionKeys,
      ),
      pattern,
    );
    _finishJoinedPatternVariables(
        {}, componentVariables, patternVariablePromotionKeys,
        location: JoinedPatternVariableLocation.singlePattern);
    flow.patternVariableDeclaration_end();
    // Stack: (Expression, Pattern)
    return patternSchema;
  }

  /// Analyzes a record pattern.  [node] is the pattern itself, and [fields]
  /// is the list of subpatterns.
  ///
  /// Returns a [RecordPatternResult] with the required type and information
  /// about reported errors.
  ///
  /// See [dispatchPattern] for the meaning of [context].
  ///
  /// Stack effect: pushes (n * Pattern) where n = fields.length.
  RecordPatternResult<Type, Error> analyzeRecordPattern(
    MatchContext<Node, Expression, Pattern, Type, Variable> context,
    Pattern node, {
    required List<RecordPatternField<Node, Pattern>> fields,
  }) {
    List<Type> demonstratedPositionalTypes = [];
    List<NamedType<Type>> demonstratedNamedTypes = [];
    void dispatchField(
      RecordPatternField<Node, Pattern> field,
      Type matchedType,
    ) {
      flow.pushSubpattern(matchedType);
      dispatchPattern(
        context.withUnnecessaryWildcardKind(null),
        field.pattern,
      );
      Type demonstratedType = flow.getMatchedValueType();
      String? name = field.name;
      if (name == null) {
        demonstratedPositionalTypes.add(demonstratedType);
      } else {
        demonstratedNamedTypes.add(new NamedType(name, demonstratedType));
      }
      flow.popSubpattern();
    }

    void dispatchFields(Type matchedType) {
      for (int i = 0; i < fields.length; i++) {
        dispatchField(fields[i], matchedType);
      }
    }

    Map<int, Error>? duplicateRecordPatternFieldErrors =
        _reportDuplicateRecordPatternFields(node, fields);

    // Build the required type.
    int requiredTypePositionalCount = 0;
    List<NamedType<Type>> requiredTypeNamedTypes = [];
    for (RecordPatternField<Node, Pattern> field in fields) {
      String? name = field.name;
      if (name == null) {
        requiredTypePositionalCount++;
      } else {
        requiredTypeNamedTypes.add(
          new NamedType(name, objectQuestionType),
        );
      }
    }
    Type requiredType = recordType(
      positional: new List.filled(
        requiredTypePositionalCount,
        objectQuestionType,
      ),
      named: requiredTypeNamedTypes,
    );
    Type matchedType = flow.getMatchedValueType();
    flow.promoteForPattern(matchedType: matchedType, knownType: requiredType);

    // Stack: ()
    RecordType<Type>? matchedRecordType = asRecordType(matchedType);
    if (matchedRecordType != null) {
      List<Type>? fieldTypes = _matchRecordTypeShape(fields, matchedRecordType);
      if (fieldTypes != null) {
        assert(fieldTypes.length == fields.length);
        for (int i = 0; i < fields.length; i++) {
          dispatchField(fields[i], fieldTypes[i]);
        }
      } else {
        dispatchFields(objectQuestionType);
      }
    } else if (operations.isDynamic(matchedType)) {
      dispatchFields(dynamicType);
    } else {
      dispatchFields(objectQuestionType);
    }
    // Stack: (n * Pattern) where n = fields.length

    Node? irrefutableContext = context.irrefutableContext;
    Error? patternTypeMismatchInIrrefutableContextError;
    if (irrefutableContext != null &&
        !operations.isAssignableTo(matchedType, requiredType)) {
      patternTypeMismatchInIrrefutableContextError =
          errors.patternTypeMismatchInIrrefutableContext(
        pattern: node,
        context: irrefutableContext,
        matchedType: matchedType,
        requiredType: requiredType,
      );
    }

    Type demonstratedType = recordType(
        positional: demonstratedPositionalTypes, named: demonstratedNamedTypes);
    flow.promoteForPattern(
        matchedType: matchedType,
        knownType: demonstratedType,
        matchFailsIfWrongType: false);
    return new RecordPatternResult(
        requiredType: requiredType,
        duplicateRecordPatternFieldErrors: duplicateRecordPatternFieldErrors,
        patternTypeMismatchInIrrefutableContextError:
            patternTypeMismatchInIrrefutableContextError);
  }

  /// Computes the type schema for a record pattern.
  ///
  /// Stack effect: none.
  Type analyzeRecordPatternSchema({
    required List<RecordPatternField<Node, Pattern>> fields,
  }) {
    List<Type> positional = [];
    List<NamedType<Type>> named = [];
    for (RecordPatternField<Node, Pattern> field in fields) {
      Type fieldType = dispatchPatternSchema(field.pattern);
      String? name = field.name;
      if (name != null) {
        named.add(new NamedType(name, fieldType));
      } else {
        positional.add(fieldType);
      }
    }
    return recordType(positional: positional, named: named);
  }

  /// Analyzes a relational pattern.  [node] is the pattern itself, and
  /// [operand] is a constant expression that will be passed to the relational
  /// operator.
  ///
  /// This method will invoke [resolveRelationalPatternOperator] to obtain
  /// information about the operator.
  ///
  /// Returns a [RelationalPatternResult] with the type of the [operand] and
  /// information about reported errors.
  ///
  /// See [dispatchPattern] for the meaning of [context].
  ///
  /// Stack effect: pushes (Expression).
  RelationalPatternResult<Type, Error> analyzeRelationalPattern(
      MatchContext<Node, Expression, Pattern, Type, Variable> context,
      Pattern node,
      Expression operand) {
    // Stack: ()
    Error? refutablePatternInIrrefutableContextError;
    Node? irrefutableContext = context.irrefutableContext;
    if (irrefutableContext != null) {
      refutablePatternInIrrefutableContextError =
          errors.refutablePatternInIrrefutableContext(
              pattern: node, context: irrefutableContext);
    }
    Type matchedValueType = flow.getMatchedValueType();
    RelationalOperatorResolution<Type>? operator =
        resolveRelationalPatternOperator(node, matchedValueType);
    Type operandContext = operator?.parameterType ?? unknownType;
    Type operandType = analyzeExpression(operand, operandContext);
    bool isEquality;
    switch (operator?.kind) {
      case RelationalOperatorKind.equals:
        isEquality = true;
        flow.equalityRelationalPattern_end(operand, operandType,
            notEqual: false);
        break;
      case RelationalOperatorKind.notEquals:
        isEquality = true;
        flow.equalityRelationalPattern_end(operand, operandType,
            notEqual: true);
        break;
      default:
        isEquality = false;
        flow.nonEqualityRelationalPattern_end();
        break;
    }
    // Stack: (Expression)
    Error? argumentTypeNotAssignableError;
    Error? operatorReturnTypeNotAssignableToBoolError;
    if (operator != null) {
      Type argumentType =
          isEquality ? operations.promoteToNonNull(operandType) : operandType;
      if (!operations.isAssignableTo(argumentType, operator.parameterType)) {
        argumentTypeNotAssignableError =
            errors.relationalPatternOperandTypeNotAssignable(
          pattern: node,
          operandType: argumentType,
          parameterType: operator.parameterType,
        );
      }
      if (!operations.isAssignableTo(operator.returnType, boolType)) {
        operatorReturnTypeNotAssignableToBoolError =
            errors.relationalPatternOperatorReturnTypeNotAssignableToBool(
          pattern: node,
          returnType: operator.returnType,
        );
      }
    }
    return new RelationalPatternResult(
        operandType: operandType,
        refutablePatternInIrrefutableContextError:
            refutablePatternInIrrefutableContextError,
        operatorReturnTypeNotAssignableToBoolError:
            operatorReturnTypeNotAssignableToBoolError,
        argumentTypeNotAssignableError: argumentTypeNotAssignableError);
  }

  /// Computes the type schema for a relational pattern.
  ///
  /// Stack effect: none.
  Type analyzeRelationalPatternSchema() {
    // Relational patterns are only allowed in refutable contexts, and refutable
    // contexts don't propagate a type schema into the scrutinee.  So this
    // code path is only reachable if the user's code contains errors.
    errors.assertInErrorRecovery();
    return unknownType;
  }

  /// Analyzes an expression of the form `switch (expression) { cases }`.
  ///
  /// Returns a [SwitchExpressionResult] with the static type of the switch
  /// expression and information about reported errors.
  ///
  /// Stack effect: pushes (Expression, n * ExpressionCase), where n is the
  /// number of cases.
  SwitchExpressionResult<Type, Error> analyzeSwitchExpression(
      Expression node, Expression scrutinee, int numCases, Type context) {
    // Stack: ()
    Type expressionType = analyzeExpression(scrutinee, unknownType);
    // Stack: (Expression)
    handleSwitchScrutinee(expressionType);
    flow.switchStatement_expressionEnd(null, scrutinee, expressionType);
    Type? lubType;
    Map<int, Error>? nonBooleanGuardErrors;
    Map<int, Type>? guardTypes;
    for (int i = 0; i < numCases; i++) {
      // Stack: (Expression, i * ExpressionCase)
      SwitchExpressionMemberInfo<Node, Expression, Variable> memberInfo =
          getSwitchExpressionMemberInfo(node, i);
      flow.switchStatement_beginAlternatives();
      flow.switchStatement_beginAlternative();
      handleSwitchBeforeAlternative(node, caseIndex: i, subIndex: 0);
      Node? pattern = memberInfo.head.pattern;
      Expression? guard;
      if (pattern != null) {
        Map<String, List<Variable>> componentVariables = {};
        Map<String, int> patternVariablePromotionKeys = {};
        dispatchPattern(
          new MatchContext<Node, Expression, Pattern, Type, Variable>(
            isFinal: false,
            switchScrutinee: scrutinee,
            componentVariables: componentVariables,
            patternVariablePromotionKeys: patternVariablePromotionKeys,
          ),
          pattern,
        );
        _finishJoinedPatternVariables(
          memberInfo.head.variables,
          componentVariables,
          patternVariablePromotionKeys,
          location: JoinedPatternVariableLocation.singlePattern,
        );
        // Stack: (Expression, i * ExpressionCase, Pattern)
        guard = memberInfo.head.guard;
        bool hasGuard = guard != null;
        if (hasGuard) {
          Type guardType = analyzeExpression(guard, boolType);
          Error? nonBooleanGuardError = _checkGuardType(guard, guardType);
          (guardTypes ??= {})[i] = guardType;
          if (nonBooleanGuardError != null) {
            (nonBooleanGuardErrors ??= {})[i] = nonBooleanGuardError;
          }
          // Stack: (Expression, i * ExpressionCase, Pattern, Expression)
        } else {
          handleNoGuard(node, i);
          // Stack: (Expression, i * ExpressionCase, Pattern, Expression)
        }
        handleCaseHead(node, memberInfo.head, caseIndex: i, subIndex: 0);
      } else {
        handleDefault(node, caseIndex: i, subIndex: 0);
      }
      flow.switchStatement_endAlternative(guard, {});
      flow.switchStatement_endAlternatives(null, hasLabels: false);
      // Stack: (Expression, i * ExpressionCase, CaseHead)
      Type type = analyzeExpression(memberInfo.expression, context);
      flow.switchStatement_afterCase();
      // Stack: (Expression, i * ExpressionCase, CaseHead, Expression)
      if (lubType == null) {
        lubType = type;
      } else {
        lubType = operations.lub(lubType, type);
      }
      finishExpressionCase(node, i);
      // Stack: (Expression, (i + 1) * ExpressionCase)
    }
    lubType ??= dynamicType;
    // Stack: (Expression, numCases * ExpressionCase)
    flow.switchStatement_end(true);
    return new SwitchExpressionResult(
        type: lubType,
        nonBooleanGuardErrors: nonBooleanGuardErrors,
        guardTypes: guardTypes);
  }

  /// Analyzes a statement of the form `switch (expression) { cases }`.
  ///
  /// Stack effect: pushes (Expression, n * StatementCase), where n is the
  /// number of cases after merging together cases that share a body.
  SwitchStatementTypeAnalysisResult<Type, Error> analyzeSwitchStatement(
      Statement node, Expression scrutinee, final int numCases) {
    // Stack: ()
    Type scrutineeType = analyzeExpression(scrutinee, unknownType);
    // Stack: (Expression)
    handleSwitchScrutinee(scrutineeType);
    flow.switchStatement_expressionEnd(node, scrutinee, scrutineeType);
    bool hasDefault = false;
    bool lastCaseTerminates = true;
    Map<int, Error>? switchCaseCompletesNormallyErrors;
    Map<int, Map<int, Error>>? nonBooleanGuardErrors;
    Map<int, Map<int, Type>>? guardTypes;
    for (int caseIndex = 0; caseIndex < numCases; caseIndex++) {
      // Stack: (Expression, numExecutionPaths * StatementCase)
      flow.switchStatement_beginAlternatives();
      // Stack: (Expression, numExecutionPaths * StatementCase,
      //         numHeads * CaseHead)
      SwitchStatementMemberInfo<Node, Statement, Expression, Variable>
          memberInfo = getSwitchStatementMemberInfo(node, caseIndex);
      List<CaseHeadOrDefaultInfo<Node, Expression, Variable>> heads =
          memberInfo.heads;
      for (int headIndex = 0; headIndex < heads.length; headIndex++) {
        CaseHeadOrDefaultInfo<Node, Expression, Variable> head =
            heads[headIndex];
        Node? pattern = head.pattern;
        flow.switchStatement_beginAlternative();
        handleSwitchBeforeAlternative(node,
            caseIndex: caseIndex, subIndex: headIndex);
        Expression? guard;
        if (pattern != null) {
          Map<String, List<Variable>> componentVariables = {};
          Map<String, int> patternVariablePromotionKeys = {};
          dispatchPattern(
            new MatchContext<Node, Expression, Pattern, Type, Variable>(
              isFinal: false,
              switchScrutinee: scrutinee,
              componentVariables: componentVariables,
              patternVariablePromotionKeys: patternVariablePromotionKeys,
            ),
            pattern,
          );
          _finishJoinedPatternVariables(
            head.variables,
            componentVariables,
            patternVariablePromotionKeys,
            location: JoinedPatternVariableLocation.singlePattern,
          );
          // Stack: (Expression, numExecutionPaths * StatementCase,
          //         numHeads * CaseHead, Pattern),
          guard = head.guard;
          if (guard != null) {
            Type guardType = analyzeExpression(guard, boolType);
            Error? nonBooleanGuardError = _checkGuardType(guard, guardType);
            ((guardTypes ??= {})[caseIndex] ??= {})[headIndex] = guardType;
            if (nonBooleanGuardError != null) {
              ((nonBooleanGuardErrors ??= {})[caseIndex] ??= {})[headIndex] =
                  nonBooleanGuardError;
            }
            // Stack: (Expression, numExecutionPaths * StatementCase,
            //         numHeads * CaseHead, Pattern, Expression),
          } else {
            handleNoGuard(node, caseIndex);
          }
          head = handleCaseHead(node, head,
              caseIndex: caseIndex, subIndex: headIndex);
          guard = head.guard;
        } else {
          hasDefault = true;
          handleDefault(node, caseIndex: caseIndex, subIndex: headIndex);
        }
        // Stack: (Expression, numExecutionPaths * StatementCase,
        //         numHeads * CaseHead),
        flow.switchStatement_endAlternative(guard, head.variables);
      }
      // Stack: (Expression, numExecutionPaths * StatementCase,
      //         numHeads * CaseHead)
      PatternVariableInfo<Variable> patternVariableInfo =
          flow.switchStatement_endAlternatives(node,
              hasLabels: memberInfo.hasLabels);
      Map<String, Variable> variables = memberInfo.variables;
      if (memberInfo.hasLabels || heads.length > 1) {
        _finishJoinedPatternVariables(
          variables,
          patternVariableInfo.componentVariables,
          patternVariableInfo.patternVariablePromotionKeys,
          location: JoinedPatternVariableLocation.sharedCaseScope,
        );
      }
      handleCase_afterCaseHeads(node, caseIndex, variables.values);
      // Stack: (Expression, numExecutionPaths * StatementCase, CaseHeads)
      // If there are joined variables, declare them.
      for (Statement statement in memberInfo.body) {
        dispatchStatement(statement);
      }
      // Stack: (Expression, numExecutionPaths * StatementCase, CaseHeads,
      //         n * Statement), where n = body.length
      lastCaseTerminates = !flow.switchStatement_afterCase();
      if (caseIndex < numCases - 1 &&
          options.nullSafetyEnabled &&
          !options.patternsEnabled &&
          !lastCaseTerminates) {
        (switchCaseCompletesNormallyErrors ??= {})[caseIndex] = errors
            .switchCaseCompletesNormally(node: node, caseIndex: caseIndex);
      }
      handleMergedStatementCase(node,
          caseIndex: caseIndex, isTerminating: lastCaseTerminates);
      // Stack: (Expression, (numExecutionPaths + 1) * StatementCase)
    }
    // Stack: (Expression, numExecutionPaths * StatementCase)
    bool isExhaustive;
    bool requiresExhaustivenessValidation;
    if (hasDefault) {
      isExhaustive = true;
      requiresExhaustivenessValidation = false;
    } else if (options.patternsEnabled) {
      requiresExhaustivenessValidation =
          isExhaustive = isAlwaysExhaustiveType(scrutineeType);
    } else {
      isExhaustive = isLegacySwitchExhaustive(node, scrutineeType);
      requiresExhaustivenessValidation = false;
    }
    flow.switchStatement_end(isExhaustive);
    return new SwitchStatementTypeAnalysisResult(
      hasDefault: hasDefault,
      isExhaustive: isExhaustive,
      lastCaseTerminates: lastCaseTerminates,
      requiresExhaustivenessValidation: requiresExhaustivenessValidation,
      scrutineeType: scrutineeType,
      switchCaseCompletesNormallyErrors: switchCaseCompletesNormallyErrors,
      nonBooleanGuardErrors: nonBooleanGuardErrors,
      guardTypes: guardTypes,
    );
  }

  /// Analyzes a variable declaration of the form `type variable;` or
  /// `var variable;`.
  ///
  /// [node] should be the AST node for the entire declaration, [variable] for
  /// the variable, and [declaredType] for the type (if present).  [isFinal] and
  /// [isLate] indicate whether this is a final declaration and/or a late
  /// declaration, respectively.
  ///
  /// Stack effect: none.
  ///
  /// Returns the inferred type of the variable.
  Type analyzeUninitializedVariableDeclaration(
      Node node, Variable variable, Type? declaredType,
      {required bool isFinal, required bool isLate}) {
    Type inferredType = declaredType ?? dynamicType;
    setVariableType(variable, inferredType);
    flow.declare(variable, inferredType, initialized: false);
    return inferredType;
  }

  /// Analyzes a wildcard pattern.  [node] is the pattern.
  ///
  /// Returns a [WildcardPattern] with information about reported errors.
  ///
  /// See [dispatchPattern] for the meaning of [context].
  ///
  /// Stack effect: none.
  WildcardPatternResult<Error> analyzeWildcardPattern({
    required MatchContext<Node, Expression, Pattern, Type, Variable> context,
    required Pattern node,
    required Type? declaredType,
  }) {
    Type matchedType = flow.getMatchedValueType();
    Node? irrefutableContext = context.irrefutableContext;
    Error? patternTypeMismatchInIrrefutableContextError;
    if (irrefutableContext != null && declaredType != null) {
      if (!operations.isAssignableTo(matchedType, declaredType)) {
        patternTypeMismatchInIrrefutableContextError =
            errors.patternTypeMismatchInIrrefutableContext(
          pattern: node,
          context: irrefutableContext,
          matchedType: matchedType,
          requiredType: declaredType,
        );
      }
    }

    bool isAlwaysMatching;
    if (declaredType != null) {
      isAlwaysMatching = flow.promoteForPattern(
          matchedType: matchedType, knownType: declaredType);
    } else {
      isAlwaysMatching = true;
    }

    UnnecessaryWildcardKind? unnecessaryWildcardKind =
        context.unnecessaryWildcardKind;
    if (isAlwaysMatching && unnecessaryWildcardKind != null) {
      errors.unnecessaryWildcardPattern(
        pattern: node,
        kind: unnecessaryWildcardKind,
      );
    }
    return new WildcardPatternResult(
        patternTypeMismatchInIrrefutableContextError:
            patternTypeMismatchInIrrefutableContextError);
  }

  /// Computes the type schema for a wildcard pattern.  [declaredType] is the
  /// explicitly declared type (if present).
  ///
  /// Stack effect: none.
  Type analyzeWildcardPatternSchema({
    required Type? declaredType,
  }) {
    return declaredType ?? unknownType;
  }

  /// If [type] is a record type, returns it.
  RecordType<Type>? asRecordType(Type type);

  /// Calls the appropriate `analyze` method according to the form of
  /// collection [element], and then adjusts the stack as needed to combine
  /// any sub-structures into a single collection element.
  ///
  /// For example, if [element] is an `if` element, calls [analyzeIfElement].
  ///
  /// Stack effect: pushes (CollectionElement).
  void dispatchCollectionElement(Node element, Object? context);

  /// Calls the appropriate `analyze` method according to the form of
  /// [expression], and then adjusts the stack as needed to combine any
  /// sub-structures into a single expression.
  ///
  /// For example, if [node] is a binary expression (`a + b`), calls
  /// [analyzeBinaryExpression].
  ///
  /// Stack effect: pushes (Expression).
  ExpressionTypeAnalysisResult<Type> dispatchExpression(
      Expression node, Type context);

  /// Calls the appropriate `analyze` method according to the form of [pattern].
  ///
  /// [context] keeps track of other contextual information pertinent to the
  /// matching of the [pattern], such as the context of the top-level pattern,
  /// and the information accumulated while matching previous patterns.
  ///
  /// Stack effect: pushes (Pattern).
  void dispatchPattern(
      MatchContext<Node, Expression, Pattern, Type, Variable> context,
      Node pattern);

  /// Calls the appropriate `analyze...Schema` method according to the form of
  /// [pattern].
  ///
  /// Stack effect: none.
  Type dispatchPatternSchema(Node pattern);

  /// Calls the appropriate `analyze` method according to the form of
  /// [statement], and then adjusts the stack as needed to combine any
  /// sub-structures into a single statement.
  ///
  /// For example, if [statement] is a `while` loop, calls [analyzeWhileLoop].
  ///
  /// Stack effect: pushes (Statement).
  void dispatchStatement(Statement statement);

  /// Infers the type for the [pattern], should be a subtype of [matchedType].
  Type downwardInferObjectPatternRequiredType({
    required Type matchedType,
    required Pattern pattern,
  });

  /// Called after visiting an expression case.
  ///
  /// [node] is the enclosing switch expression, and [caseIndex] is the index of
  /// this code path within the switch expression's cases.
  ///
  /// Stack effect: pops (CaseHead, Expression) and pushes (ExpressionCase).
  void finishExpressionCase(Expression node, int caseIndex);

  void finishJoinedPatternVariable(
    Variable variable, {
    required JoinedPatternVariableLocation location,
    required JoinedPatternVariableInconsistency inconsistency,
    required bool isFinal,
    required Type type,
  });

  /// If the [element] is a map pattern entry, returns it.
  MapPatternEntry<Expression, Pattern>? getMapPatternEntry(Node element);

  /// If [node] is [isRestPatternElement], returns its optional pattern.
  Pattern? getRestPatternElementPattern(Node node);

  /// Returns an [ExpressionCaseInfo] object describing the [index]th `case` or
  /// `default` clause in the switch expression [node].
  ///
  /// Note: it is allowed for the client's AST nodes for `case` and `default`
  /// clauses to implement [ExpressionCaseInfo], in which case this method can
  /// simply return the [index]th `case` or `default` clause.
  ///
  /// See [analyzeSwitchExpression].
  SwitchExpressionMemberInfo<Node, Expression, Variable>
      getSwitchExpressionMemberInfo(Expression node, int index);

  /// Returns a [StatementCaseInfo] object describing the [index]th `case` or
  /// `default` clause in the switch statement [node].
  ///
  /// Note: it is allowed for the client's AST nodes for `case` and `default`
  /// clauses to implement [StatementCaseInfo], in which case this method can
  /// simply return the [index]th `case` or `default` clause.
  ///
  /// See [analyzeSwitchStatement].
  SwitchStatementMemberInfo<Node, Statement, Expression, Variable>
      getSwitchStatementMemberInfo(Statement node, int caseIndex);

  /// Returns the type of [variable].
  Type getVariableType(Variable variable);

  /// Called after visiting the pattern in `if-case` statement.
  void handle_ifCaseStatement_afterPattern({required Statement node}) {}

  /// Called after visiting the expression of an `if` element.
  void handle_ifElement_conditionEnd(Node node) {}

  /// Called after visiting the `else` element of an `if` element.
  void handle_ifElement_elseEnd(Node node, Node ifFalse) {}

  /// Called after visiting the `then` element of an `if` element.
  void handle_ifElement_thenEnd(Node node, Node ifTrue) {}

  /// Called after visiting the expression of an `if` statement.
  void handle_ifStatement_conditionEnd(Statement node) {}

  /// Called after visiting the `else` statement of an `if` statement.
  void handle_ifStatement_elseEnd(Statement node, Statement ifFalse) {}

  /// Called after visiting the `then` statement of an `if` statement.
  void handle_ifStatement_thenEnd(Statement node, Statement ifTrue) {}

  /// Called after visiting the left hand side of a logical-or (`||`) pattern.
  void handle_logicalOrPattern_afterLhs(Pattern node) {}

  /// Called after visiting a merged set of `case` / `default` clauses.
  ///
  /// [node] is the enclosing switch statement, [caseIndex] is the index of the
  /// merged `case` or `default` group.
  ///
  /// Stack effect: pops (numHeads * CaseHead) and pushes (CaseHeads).
  void handleCase_afterCaseHeads(
      Statement node, int caseIndex, Iterable<Variable> variables);

  /// Called after visiting a single `case` clause, consisting of a pattern and
  /// an optional guard.
  ///
  /// [node] is the enclosing switch statement or switch expression,
  /// [head] is the head to be handled, and
  /// [caseIndex] is the index of the `case` clause.
  ///
  /// Returns the updated case head.
  ///
  /// Stack effect: pops (Pattern, Expression) and pushes (CaseHead).
  CaseHeadOrDefaultInfo<Node, Expression, Variable> handleCaseHead(
      Node node, CaseHeadOrDefaultInfo<Node, Expression, Variable> head,
      {required int caseIndex, required int subIndex});

  /// Called after visiting a `default` clause.
  ///
  /// [node] is the enclosing switch statement or switch expression and
  /// [caseIndex] is the index of the `default` clause.
  /// [subIndex] is the index of the case head.
  ///
  /// Stack effect: pushes (CaseHead).
  void handleDefault(
    Node node, {
    required int caseIndex,
    required int subIndex,
  });

  /// Called after visiting a rest element in a list pattern.
  ///
  /// Stack effect: pushes (Pattern).
  void handleListPatternRestElement(Pattern container, Node restElement);

  /// Called after visiting an entry element in a map pattern.
  ///
  /// Stack effect: pushes (MapPatternElement).
  void handleMapPatternEntry(
      Pattern container, Node entryElement, Type keyType);

  /// Called after visiting a rest element in a map pattern.
  ///
  /// Stack effect: pushes (MapPatternElement).
  void handleMapPatternRestElement(Pattern container, Node restElement);

  /// Called after visiting a merged statement case.
  ///
  /// [node] is enclosing switch statement, [caseIndex] is the index of the
  /// merged `case` or `default` group.
  ///
  /// If [isTerminating] is `true`, then flow analysis has determined that the
  /// case ends in a construct that doesn't complete normally (e.g. a `break`,
  /// `return`, `continue`, `throw`, or infinite loop); the client can use this
  /// to determine whether a jump is needed to the end of the switch statement.
  ///
  /// Stack effect: pops (CaseHeads, numStatements * Statement) and pushes
  /// (StatementCase).
  void handleMergedStatementCase(Statement node,
      {required int caseIndex, required bool isTerminating});

  /// Called when visiting a syntactic construct where there is an implicit
  /// no-op collection element.  For example, this is called in place of the
  /// missing `else` part of an `if` element that lacks an `else` clause.
  ///
  /// Stack effect: pushes (CollectionElement).
  void handleNoCollectionElement(Node node);

  /// Called when visiting a `case` that lacks a guard clause.  Since the lack
  /// of a guard clause is semantically equivalent to `when true`, this method
  /// should behave similarly to visiting the boolean literal `true`.
  ///
  /// [node] is the enclosing switch statement, switch expression, or `if`, and
  /// [caseIndex] is the index of the `case` within [node].
  ///
  /// Stack effect: pushes (Expression).
  void handleNoGuard(Node node, int caseIndex);

  /// Called when visiting a syntactic construct where there is an implicit
  /// no-op statement.  For example, this is called in place of the missing
  /// `else` part of an `if` statement that lacks an `else` clause.
  ///
  /// Stack effect: pushes (Statement).
  void handleNoStatement(Statement node);

  /// Called before visiting a single `case` or `default` clause.
  ///
  /// [node] is the enclosing switch statement or switch expression and
  /// [caseIndex] is the index of the `case` or `default` clause.
  /// [subIndex] is the index of the case head.
  void handleSwitchBeforeAlternative(Node node,
      {required int caseIndex, required int subIndex});

  /// Called after visiting the scrutinee part of a switch statement or switch
  /// expression.  This is a hook to allow the client to start exhaustiveness
  /// analysis.
  ///
  /// [type] is the static type of the scrutinee expression.
  ///
  /// TODO(paulberry): move exhaustiveness analysis into the shared code and
  /// eliminate this method.
  ///
  /// Stack effect: none.
  void handleSwitchScrutinee(Type type);

  /// Queries whether [type] is an "always-exhaustive" type (as defined in the
  /// patterns spec).  Exhaustive types are types for which the switch statement
  /// is required to be exhaustive when patterns support is enabled.
  bool isAlwaysExhaustiveType(Type type);

  /// Queries whether the switch statement or expression represented by [node]
  /// was exhaustive.  [expressionType] is the static type of the scrutinee.
  ///
  /// Will only be called if the switch statement or expression lacks a
  /// `default` clause, and patterns support is disabled.
  bool isLegacySwitchExhaustive(Node node, Type expressionType);

  /// Returns whether [node] is a rest element in a list or map pattern.
  bool isRestPatternElement(Node node);

  /// Returns whether [node] is final.
  bool isVariableFinal(Variable node);

  /// Queries whether [pattern] is a variable pattern.
  bool isVariablePattern(Node pattern);

  /// Returns the type `Iterable`, with type argument [elementType].
  Type iterableType(Type elementType);

  /// Returns the type `List`, with type argument [elementType].
  Type listType(Type elementType);

  /// Returns the type `Map`, with type arguments.
  Type mapType({
    required Type keyType,
    required Type valueType,
  });

  /// Builds the client specific record type.
  Type recordType(
      {required List<Type> positional, required List<NamedType<Type>> named});

  /// Returns the type of the property in [receiverType] that corresponds to
  /// the name of the [field].  If the property cannot be resolved, the client
  /// should report an error, and return `dynamic` for recovery.
  Type resolveObjectPatternPropertyGet({
    required Type receiverType,
    required RecordPatternField<Node, Pattern> field,
  });

  /// Resolves the relational operator for [node] assuming that the value being
  /// matched has static type [matchedValueType].
  ///
  /// If no operator is found, `null` should be returned.  (This could happen
  /// either because the code is invalid, or because [matchedValueType] is
  /// `dynamic`).
  RelationalOperatorResolution<Type>? resolveRelationalPatternOperator(
      Pattern node, Type matchedValueType);

  /// Records that type inference has assigned a [type] to a [variable].  This
  /// is called once per variable, regardless of whether the variable's type is
  /// explicit or inferred.
  void setVariableType(Variable variable, Type type);

  /// Returns the type `Stream`, with type argument [elementType].
  Type streamType(Type elementType);

  /// Computes the type that should be inferred for an implicitly typed variable
  /// whose initializer expression has static type [type].
  Type variableTypeFromInitializerType(Type type);

  /// Common functionality shared by [analyzeIfStatement] and
  /// [analyzeIfCaseStatement].
  ///
  /// Stack effect: pushes (Statement ifTrue, Statement ifFalse).
  void _analyzeIfCommon(Statement node, Statement ifTrue, Statement? ifFalse) {
    // Stack: ()
    dispatchStatement(ifTrue);
    handle_ifStatement_thenEnd(node, ifTrue);
    // Stack: (Statement ifTrue)
    if (ifFalse == null) {
      handleNoStatement(node);
      flow.ifStatement_end(false);
    } else {
      flow.ifStatement_elseBegin();
      dispatchStatement(ifFalse);
      flow.ifStatement_end(true);
      handle_ifStatement_elseEnd(node, ifFalse);
    }
    // Stack: (Statement ifTrue, Statement ifFalse)
  }

  /// Common functionality shared by [analyzeIfElement] and
  /// [analyzeIfCaseElement].
  ///
  /// Stack effect: pushes (CollectionElement ifTrue,
  /// CollectionElement ifFalse).
  void _analyzeIfElementCommon(
      Node node, Node ifTrue, Node? ifFalse, Object? context) {
    // Stack: ()
    dispatchCollectionElement(ifTrue, context);
    handle_ifElement_thenEnd(node, ifTrue);
    // Stack: (CollectionElement ifTrue)
    if (ifFalse == null) {
      handleNoCollectionElement(node);
      flow.ifStatement_end(false);
    } else {
      flow.ifStatement_elseBegin();
      dispatchCollectionElement(ifFalse, context);
      flow.ifStatement_end(true);
      handle_ifElement_elseEnd(node, ifFalse);
    }
    // Stack: (CollectionElement ifTrue, CollectionElement ifFalse)
  }

  Error? _checkGuardType(Expression expression, Type type) {
    // TODO(paulberry): harmonize this with analyzer's checkForNonBoolExpression
    // TODO(paulberry): spec says the type must be `bool` or `dynamic`.  This
    // logic permits `T extends bool`, `T promoted to bool`, or `Never`.  What
    // do we want?
    if (!operations.isAssignableTo(type, boolType)) {
      return errors.nonBooleanCondition(node: expression);
    }
    return null;
  }

  void _finishJoinedPatternVariables(
    Map<String, Variable> variables,
    Map<String, List<Variable>> componentVariables,
    Map<String, int> patternVariablePromotionKeys, {
    required JoinedPatternVariableLocation location,
  }) {
    assert(() {
      // Every entry in `variables` should match a variable we know about.
      for (String variableName in variables.keys) {
        assert(patternVariablePromotionKeys.containsKey(variableName));
      }
      return true;
    }());
    for (MapEntry<String, int> entry in patternVariablePromotionKeys.entries) {
      String variableName = entry.key;
      int promotionKey = entry.value;
      Variable? variable = variables[variableName];
      List<Variable> components = componentVariables[variableName] ?? [];
      bool isFirst = true;
      Type? typeIfConsistent;
      bool? isFinalIfConsistent;
      bool isIdenticalToComponent = false;
      for (Variable component in components) {
        if (identical(variable, component)) {
          isIdenticalToComponent = true;
        }
        Type componentType = getVariableType(component);
        bool isComponentFinal = isVariableFinal(component);
        if (isFirst) {
          typeIfConsistent = componentType;
          isFinalIfConsistent = isComponentFinal;
          isFirst = false;
        } else {
          bool inconsistencyFound = false;
          if (typeIfConsistent != null &&
              !_structurallyEqualAfterNormTypes(
                  typeIfConsistent, componentType)) {
            typeIfConsistent = null;
            inconsistencyFound = true;
          }
          if (isFinalIfConsistent != null &&
              isFinalIfConsistent != isComponentFinal) {
            isFinalIfConsistent = null;
            inconsistencyFound = true;
          }
          if (inconsistencyFound &&
              location == JoinedPatternVariableLocation.singlePattern &&
              variable != null) {
            errors.inconsistentJoinedPatternVariable(
                variable: variable, component: component);
          }
        }
      }
      if (variable != null) {
        if (!isIdenticalToComponent) {
          finishJoinedPatternVariable(variable,
              location: location,
              inconsistency: typeIfConsistent != null &&
                      isFinalIfConsistent != null
                  ? JoinedPatternVariableInconsistency.none
                  : JoinedPatternVariableInconsistency.differentFinalityOrType,
              isFinal: isFinalIfConsistent ?? false,
              type: typeIfConsistent ?? errorType);
          flow.assignMatchedPatternVariable(variable, promotionKey);
        }
      }
    }
  }

  /// If the shape described by [fields] is the same as the shape of the
  /// [matchedType], returns matched types for each field in [fields].
  /// Otherwise returns `null`.
  List<Type>? _matchRecordTypeShape(
    List<RecordPatternField<Node, Pattern>> fields,
    RecordType<Type> matchedType,
  ) {
    Map<String, Type> matchedTypeNamed = {};
    for (NamedType<Type> namedField in matchedType.named) {
      matchedTypeNamed[namedField.name] = namedField.type;
    }

    List<Type> result = [];
    int positionalIndex = 0;
    int namedCount = 0;
    for (RecordPatternField<Node, Pattern> field in fields) {
      Type? fieldType;
      String? name = field.name;
      if (name != null) {
        fieldType = matchedTypeNamed[name];
        if (fieldType == null) {
          return null;
        }
        namedCount++;
      } else {
        if (positionalIndex >= matchedType.positional.length) {
          return null;
        }
        fieldType = matchedType.positional[positionalIndex++];
      }
      result.add(fieldType);
    }
    if (positionalIndex != matchedType.positional.length) {
      return null;
    }
    if (namedCount != matchedTypeNamed.length) {
      return null;
    }

    assert(result.length == fields.length);
    return result;
  }

  /// Reports errors for duplicate named record fields.
  Map<int, Error>? _reportDuplicateRecordPatternFields(
      Pattern pattern, List<RecordPatternField<Node, Pattern>> fields) {
    Map<int, Error>? errorResults;
    Map<String, RecordPatternField<Node, Pattern>> nameToField = {};
    for (int i = 0; i < fields.length; i++) {
      RecordPatternField<Node, Pattern> field = fields[i];
      String? name = field.name;
      if (name != null) {
        RecordPatternField<Node, Pattern>? original = nameToField[name];
        if (original != null) {
          (errorResults ??= {})[i] = errors.duplicateRecordPatternField(
            objectOrRecordPattern: pattern,
            name: name,
            original: original,
            duplicate: field,
          );
        } else {
          nameToField[name] = field;
        }
      }
    }
    return errorResults;
  }

  bool _structurallyEqualAfterNormTypes(Type type1, Type type2) {
    Type norm1 = operations.normalize(type1);
    Type norm2 = operations.normalize(type2);
    return operations.areStructurallyEqual(norm1, norm2);
  }
}

/// Interface used by the shared [TypeAnalyzer] logic to report error conditions
/// up to the client during the "visit" phase of type analysis.
abstract class TypeAnalyzerErrors<
    Node extends Object,
    Statement extends Node,
    Expression extends Node,
    Variable extends Object,
    Type extends Object,
    Pattern extends Node,
    Error> implements TypeAnalyzerErrorsBase {
  /// Called if pattern support is disabled and a case constant's static type
  /// doesn't properly match the scrutinee's static type.
  Error caseExpressionTypeMismatch(
      {required Expression scrutinee,
      required Expression caseExpression,
      required Type scrutineeType,
      required Type caseExpressionType,
      required bool nullSafetyEnabled});

  /// Called for variable that is assigned more than once.
  ///
  /// Returns an error object that is passed on the the caller.
  Error duplicateAssignmentPatternVariable({
    required Variable variable,
    required Pattern original,
    required Pattern duplicate,
  });

  /// Called for a pair of named fields have the same name.
  Error duplicateRecordPatternField({
    required Pattern objectOrRecordPattern,
    required String name,
    required RecordPatternField<Node, Pattern> original,
    required RecordPatternField<Node, Pattern> duplicate,
  });

  /// Called for a duplicate rest pattern found in a list or map pattern.
  Error duplicateRestPattern({
    required Pattern mapOrListPattern,
    required Node original,
    required Node duplicate,
  });

  /// Called when both branches have variables with the same name, but these
  /// variables either don't have the same finality, or their `NORM` types
  /// are not structurally equal.
  void inconsistentJoinedPatternVariable({
    required Variable variable,
    required Variable component,
  });

  /// Called when a null-assert or null-check pattern is used with the matched
  /// type that is strictly non-nullable, so the null check is not necessary.
  Error matchedTypeIsStrictlyNonNullable({
    required Pattern pattern,
    required Type matchedType,
  });

  /// Called when the matched type of a cast pattern is a subtype of the
  /// required type, so the cast is not necessary.
  void matchedTypeIsSubtypeOfRequired({
    required Pattern pattern,
    required Type matchedType,
    required Type requiredType,
  });

  /// Called if the static type of a condition is not assignable to `bool`.
  Error nonBooleanCondition({required Expression node});

  /// Called if a pattern is illegally used in a variable declaration statement
  /// that is marked `late`, and that pattern is not allowed in such a
  /// declaration.  The only kind of pattern that may be used in a late variable
  /// declaration is a variable pattern.
  ///
  /// [pattern] is the AST node of the illegal pattern.
  void patternDoesNotAllowLate({required Node pattern});

  /// Called if in a pattern `for-in` statement or element, the [expression]
  /// that should be an `Iterable` (or dynamic) is actually not.
  ///
  /// [expressionType] is the actual type of the [expression].
  Error patternForInExpressionIsNotIterable({
    required Node node,
    required Expression expression,
    required Type expressionType,
  });

  /// Called if, for a pattern in an irrefutable context, the matched type of
  /// the pattern is not assignable to the required type.
  ///
  /// [pattern] is the AST node of the pattern with the type error, [context] is
  /// the containing AST node that established an irrefutable context,
  /// [matchedType] is the matched type, and [requiredType] is the required
  /// type.
  Error patternTypeMismatchInIrrefutableContext(
      {required Pattern pattern,
      required Node context,
      required Type matchedType,
      required Type requiredType});

  /// Called if a refutable pattern is illegally used in an irrefutable context.
  ///
  /// [pattern] is the AST node of the refutable pattern, and [context] is the
  /// containing AST node that established an irrefutable context.
  ///
  /// TODO(paulberry): move this error reporting to the parser.
  Error refutablePatternInIrrefutableContext(
      {required Node pattern, required Node context});

  /// Called if the operand of the [pattern] has the type [operandType], which
  /// is not assignable to [parameterType] of the invoked relational operator.
  Error relationalPatternOperandTypeNotAssignable({
    required Pattern pattern,
    required Type operandType,
    required Type parameterType,
  });

  /// Called if the [returnType] of the invoked relational operator is not
  /// assignable to `bool`.
  Error relationalPatternOperatorReturnTypeNotAssignableToBool({
    required Pattern pattern,
    required Type returnType,
  });

  /// Called if a rest pattern inside a map pattern is not the last element.
  ///
  /// [node] is the map pattern.  [element] is the rest pattern.
  void restPatternNotLastInMap({required Pattern node, required Node element});

  /// Called if a rest pattern inside a map pattern has a subpattern.
  ///
  /// [node] is the map pattern.  [element] is the rest pattern.
  void restPatternWithSubPatternInMap(
      {required Pattern node, required Node element});

  /// Called if one of the case bodies of a switch statement completes normally
  /// (other than the last case body), and the "patterns" feature is not
  /// enabled.
  ///
  /// [node] is the AST node of the switch statement.  [caseIndex] is the index
  /// of the merged case with the erroneous case body.
  Error switchCaseCompletesNormally(
      {required Statement node, required int caseIndex});

  /// Called when a wildcard pattern appears in the context where it is not
  /// necessary, e.g. `0 && var _` vs. `[var _]`, and does not add anything
  /// to type promotion, e.g. `final x = 0; if (x case int _ && > 0) {}`.
  void unnecessaryWildcardPattern({
    required Pattern pattern,
    required UnnecessaryWildcardKind kind,
  });
}

/// Base class for error reporting callbacks that might be reported either in
/// the "pre-visit" or the "visit" phase of type analysis.
abstract class TypeAnalyzerErrorsBase {
  /// Called when the [TypeAnalyzer] encounters a condition which should be
  /// impossible if the user's code is free from static errors, but which might
  /// arise as a result of error recovery.  To verify this invariant, the client
  /// should double check (preferably using an assertion) that at least one
  /// error is reported.
  ///
  /// Note that the error might be reported after this method is called.
  void assertInErrorRecovery();
}

/// Options affecting the behavior of [TypeAnalyzer].
///
/// The client is free to `implement` or `extend` this class.
class TypeAnalyzerOptions {
  final bool nullSafetyEnabled;

  final bool patternsEnabled;

  TypeAnalyzerOptions(
      {required this.nullSafetyEnabled, required this.patternsEnabled});
}
