// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis_operations.dart'
    as shared;
import 'package:_fe_analyzer_shared/src/type_inference/null_shorting.dart';
import 'package:_fe_analyzer_shared/src/type_inference/type_analysis_result.dart'
    as shared;
import 'package:_fe_analyzer_shared/src/type_inference/type_analysis_result.dart';
import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer.dart'
    as shared;
import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer.dart';
import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer_operations.dart'
    as shared;
import 'package:_fe_analyzer_shared/src/types/shared_type.dart';
import 'package:analyzer/dart/analysis/analysis_options.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/syntactic_entity.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/scope.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/source/source.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/extensions.dart';
import 'package:analyzer/src/dart/element/generic_inferrer.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/scope.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_constraint_gatherer.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/element/type_schema.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/dart/resolver/annotation_resolver.dart';
import 'package:analyzer/src/dart/resolver/assignment_expression_resolver.dart';
import 'package:analyzer/src/dart/resolver/binary_expression_resolver.dart';
import 'package:analyzer/src/dart/resolver/body_inference_context.dart';
import 'package:analyzer/src/dart/resolver/constructor_reference_resolver.dart';
import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
import 'package:analyzer/src/dart/resolver/for_resolver.dart';
import 'package:analyzer/src/dart/resolver/function_expression_invocation_resolver.dart';
import 'package:analyzer/src/dart/resolver/function_expression_resolver.dart';
import 'package:analyzer/src/dart/resolver/function_reference_resolver.dart';
import 'package:analyzer/src/dart/resolver/instance_creation_expression_resolver.dart';
import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
import 'package:analyzer/src/dart/resolver/invocation_inferrer.dart';
import 'package:analyzer/src/dart/resolver/lexical_lookup.dart';
import 'package:analyzer/src/dart/resolver/list_pattern_resolver.dart';
import 'package:analyzer/src/dart/resolver/postfix_expression_resolver.dart';
import 'package:analyzer/src/dart/resolver/prefix_expression_resolver.dart';
import 'package:analyzer/src/dart/resolver/prefixed_identifier_resolver.dart';
import 'package:analyzer/src/dart/resolver/property_element_resolver.dart';
import 'package:analyzer/src/dart/resolver/record_literal_resolver.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/dart/resolver/shared_type_analyzer.dart';
import 'package:analyzer/src/dart/resolver/simple_identifier_resolver.dart';
import 'package:analyzer/src/dart/resolver/this_lookup.dart';
import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
import 'package:analyzer/src/dart/resolver/typed_literal_resolver.dart';
import 'package:analyzer/src/dart/resolver/variable_declaration_resolver.dart';
import 'package:analyzer/src/dart/resolver/yield_statement_resolver.dart';
import 'package:analyzer/src/diagnostic/diagnostic.dart';
import 'package:analyzer/src/error/base_or_final_type_verifier.dart';
import 'package:analyzer/src/error/bool_expression_verifier.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/error/dead_code_verifier.dart';
import 'package:analyzer/src/error/inference_error.dart';
import 'package:analyzer/src/error/nullable_dereference_verifier.dart';
import 'package:analyzer/src/error/super_formal_parameters_verifier.dart';
import 'package:analyzer/src/generated/element_resolver.dart';
import 'package:analyzer/src/generated/error_detection_helpers.dart';
import 'package:analyzer/src/generated/inference_log.dart';
import 'package:analyzer/src/generated/static_type_analyzer.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/generated/variable_type_provider.dart';
import 'package:analyzer/src/util/ast_data_extractor.dart';
import 'package:analyzer/src/utilities/extensions/element.dart';
import 'package:analyzer/src/utilities/extensions/object.dart';

/// Function determining which source files should have inference logging
/// enabled.
///
/// By default, no files have inference logging enabled.
bool Function(Source) inferenceLoggingPredicate = (_) => false;

typedef SharedMatchContext =
    shared.MatchContext<
      AstNodeImpl,
      ExpressionImpl,
      DartPatternImpl,
      SharedTypeView,
      PromotableElementImpl
    >;

typedef SharedPatternField =
    shared.RecordPatternField<PatternFieldImpl, DartPatternImpl>;

/// A function which returns [NonPromotionReason]s that various types are not
/// promoted.
typedef WhyNotPromotedGetter =
    Map<SharedTypeView, NonPromotionReason> Function();

/// The context shared between different units of the same library.
final class LibraryResolutionContext {
  /// The declarations for [VariableFragment]s.
  final Map<VariableFragment, VariableDeclaration> _variableNodes =
      Map.identity();
}

/// Instances of the class `ResolverVisitor` are used to resolve the nodes
/// within a single compilation unit.
class ResolverVisitor extends ThrowingAstVisitor<void>
    with
        ErrorDetectionHelpers,
        TypeAnalyzer<
          AstNodeImpl,
          StatementImpl,
          ExpressionImpl,
          PromotableElementImpl,
          DartPatternImpl,
          void,
          InterfaceTypeImpl,
          InterfaceElementImpl
        >,
        // TODO(paulberry): not yet used.
        NullShortingMixin<
          Null,
          ExpressionImpl,
          PromotableElementImpl,
          SharedTypeView
        > {
  /// Debug-only: if `true`, manipulations of [_rewriteStack] performed by
  /// [popRewrite], [pushRewrite], and [replaceExpression] will be printed.
  static const bool _debugRewriteStack = false;

  /// The element for the library containing the compilation unit being visited.
  final LibraryElementImpl definingLibrary;

  /// The library fragment being visited.
  final LibraryFragmentImpl libraryFragment;

  /// The context shared between different units of the same library.
  final LibraryResolutionContext libraryResolutionContext;

  /// If the resolver visitor is visiting a switch statement and patterns
  /// support is disabled, the tracker that determines whether the switch is
  /// exhaustive.
  SwitchExhaustiveness? legacySwitchExhaustiveness;

  @override
  final TypeAnalyzerOptions typeAnalyzerOptions;

  @override
  late final SharedTypeAnalyzerErrors errors = SharedTypeAnalyzerErrors(
    diagnosticReporter,
  );

  /// The source representing the compilation unit being visited.
  final Source source;

  /// The object used to access the types from the core library.
  final TypeProviderImpl typeProvider;

  @override
  final DiagnosticReporter diagnosticReporter;

  /// The analysis options used by this resolver.
  final AnalysisOptions analysisOptions;

  /// The class containing the AST nodes being visited,
  /// or `null` if we are not in the scope of a class.
  InterfaceElementImpl? enclosingClass;

  /// The element representing the extension containing the AST nodes being
  /// visited, or `null` if we are not in the scope of an extension.
  ExtensionElementImpl? enclosingExtension;

  /// The element representing the function containing the current node, or
  /// `null` if the current node is not contained in a function.
  ExecutableElementImpl? enclosingFunction;

  /// The manager for the inheritance mappings.
  @override
  final InheritanceManager3 inheritance;

  /// The feature set that is enabled for the current unit.
  final FeatureSet _featureSet;

  /// Helper for checking that subtypes of a base or final type must be base,
  /// final, or sealed.
  late final BaseOrFinalTypeVerifier baseOrFinalTypeVerifier;

  /// Helper for checking expression that should have the `bool` type.
  late final BoolExpressionVerifier boolExpressionVerifier =
      BoolExpressionVerifier(
        resolver: this,
        diagnosticReporter: diagnosticReporter,
        nullableDereferenceVerifier: nullableDereferenceVerifier,
      );

  /// Helper for checking potentially nullable dereferences.
  late final NullableDereferenceVerifier nullableDereferenceVerifier =
      NullableDereferenceVerifier(
        typeSystem: typeSystem,
        diagnosticReporter: diagnosticReporter,
        resolver: this,
      );

  /// Helper for extension method resolution.
  late final ExtensionMemberResolver extensionResolver =
      ExtensionMemberResolver(this);

  /// Helper for resolving properties on types.
  late final TypePropertyResolver typePropertyResolver = TypePropertyResolver(
    this,
  );

  /// Helper for resolving [ListLiteral] and [SetOrMapLiteral].
  late final TypedLiteralResolver _typedLiteralResolver = TypedLiteralResolver(
    this,
    typeSystem,
    typeProvider,
    analysisOptions,
  );

  late final AssignmentExpressionResolver _assignmentExpressionResolver =
      AssignmentExpressionResolver(resolver: this);
  late final BinaryExpressionResolver _binaryExpressionResolver;
  late final ConstructorReferenceResolver _constructorReferenceResolver =
      ConstructorReferenceResolver(this);
  late final FunctionExpressionInvocationResolver
  _functionExpressionInvocationResolver;
  late final FunctionExpressionResolver _functionExpressionResolver;
  late final ForResolver _forResolver;
  late final PostfixExpressionResolver _postfixExpressionResolver;
  late final PrefixedIdentifierResolver _prefixedIdentifierResolver;
  late final PrefixExpressionResolver _prefixExpressionResolver;
  late final VariableDeclarationResolver _variableDeclarationResolver;
  late final YieldStatementResolver _yieldStatementResolver;

  late final NullSafetyDeadCodeVerifier nullSafetyDeadCodeVerifier;

  late final InvocationInferenceHelper inferenceHelper;

  /// The object used to resolve the element associated with the current node.
  late final ElementResolver elementResolver;

  /// The object used to compute the type associated with the current node.
  late final StaticTypeAnalyzer typeAnalyzer;

  /// The type system in use during resolution.
  @override
  final TypeSystemImpl typeSystem;

  /// Inference context information for the current function body, if the
  /// current node is inside a function body.
  BodyInferenceContext? _bodyContext;

  /// If a class, or mixin, is being resolved, the type of the class.
  /// Otherwise `null`.
  TypeImpl? _thisType;

  final FlowAnalysisHelper flowAnalysis;

  /// Stack of expressions which we have not yet finished visiting, that should
  /// terminate a null-shorting expression.
  ///
  /// The stack contains a `null` sentinel as its first entry so that it is
  /// always safe to use `.last` to examine the top of the stack.
  final List<Expression?> _unfinishedNullShorts = [null];

  late final FunctionReferenceResolver _functionReferenceResolver;

  late final InstanceCreationExpressionResolver
  _instanceCreationExpressionResolver = InstanceCreationExpressionResolver(
    this,
  );

  late final SimpleIdentifierResolver _simpleIdentifierResolver =
      SimpleIdentifierResolver(this);

  late final PropertyElementResolver _propertyElementResolver =
      PropertyElementResolver(this);

  late final RecordLiteralResolver _recordLiteralResolver =
      RecordLiteralResolver(resolver: this);

  late final AnnotationResolver _annotationResolver = AnnotationResolver(this);

  late final ListPatternResolver listPatternResolver = ListPatternResolver(
    this,
  );

  final bool genericMetadataIsEnabled;

  final bool inferenceUsingBoundsIsEnabled;

  /// Stack for obtaining rewritten expressions.  Prior to visiting an
  /// expression, a caller may push the expression on this stack; if
  /// [replaceExpression] is later called, it will update the top of the stack
  /// to point to the rewritten expression.
  ///
  /// The stack sometimes contains `null`s.  These account for situations where
  /// it's necessary to push a value onto the stack to balance a later pop, but
  /// there is no suitable expression to push.
  final List<ExpressionImpl?> _rewriteStack = [];

  /// Debug-only expando mapping AST nodes to the nodes they were replaced with
  /// by [replaceExpression].  This is used by [dispatchExpression] as a sanity
  /// check to make sure the expression it pops off the [_rewriteStack] is
  /// actually correct.
  late final Expando<AstNode> _replacements = Expando();

  /// Initialize a newly created visitor to resolve the nodes in an AST node.
  ///
  /// The [definingLibrary] is the element for the library containing the node
  /// being visited. The [source] is the source representing the compilation
  /// unit containing the node being visited. The [typeProvider] is the object
  /// used to access the types from the core library. The [diagnosticListener]
  /// is the diagnostic listener that will be informed of any diagnostics that
  /// are found during resolution.
  ResolverVisitor(
    InheritanceManager3 inheritanceManager,
    LibraryElementImpl definingLibrary,
    LibraryResolutionContext libraryResolutionContext,
    Source source,
    TypeProvider typeProvider,
    DiagnosticListener diagnosticListener, {
    required LibraryFragmentImpl libraryFragment,
    required FeatureSet featureSet,
    required AnalysisOptions analysisOptions,
    required FlowAnalysisHelper flowAnalysisHelper,
    required TypeAnalyzerOptions typeAnalyzerOptions,
  }) : this._(
         inheritanceManager,
         definingLibrary,
         libraryResolutionContext,
         source,
         definingLibrary.typeSystem,
         typeProvider as TypeProviderImpl,
         DiagnosticReporter(diagnosticListener, source),
         featureSet,
         analysisOptions,
         flowAnalysisHelper,
         libraryFragment: libraryFragment,
         typeAnalyzerOptions: typeAnalyzerOptions,
       );

  ResolverVisitor._(
    this.inheritance,
    this.definingLibrary,
    this.libraryResolutionContext,
    this.source,
    this.typeSystem,
    this.typeProvider,
    this.diagnosticReporter,
    FeatureSet featureSet,
    this.analysisOptions,
    this.flowAnalysis, {
    required this.libraryFragment,
    required this.typeAnalyzerOptions,
  }) : _featureSet = featureSet,
       genericMetadataIsEnabled = definingLibrary.featureSet.isEnabled(
         Feature.generic_metadata,
       ),
       inferenceUsingBoundsIsEnabled = definingLibrary.featureSet.isEnabled(
         Feature.inference_using_bounds,
       ),
       baseOrFinalTypeVerifier = BaseOrFinalTypeVerifier(
         definingLibrary: definingLibrary,
         diagnosticReporter: diagnosticReporter,
       ) {
    inferenceHelper = InvocationInferenceHelper(
      resolver: this,
      diagnosticReporter: diagnosticReporter,
      typeSystem: typeSystem,
      dataForTesting:
          flowAnalysis.dataForTesting != null
              ? TypeConstraintGenerationDataForTesting()
              : null,
    );
    _binaryExpressionResolver = BinaryExpressionResolver(resolver: this);
    _functionExpressionInvocationResolver =
        FunctionExpressionInvocationResolver(resolver: this);
    _functionExpressionResolver = FunctionExpressionResolver(resolver: this);
    _forResolver = ForResolver(resolver: this);
    _postfixExpressionResolver = PostfixExpressionResolver(resolver: this);
    _prefixedIdentifierResolver = PrefixedIdentifierResolver(this);
    _prefixExpressionResolver = PrefixExpressionResolver(resolver: this);
    _variableDeclarationResolver = VariableDeclarationResolver(
      resolver: this,
      strictInference: analysisOptions.strictInference,
    );
    _yieldStatementResolver = YieldStatementResolver(resolver: this);
    nullSafetyDeadCodeVerifier = NullSafetyDeadCodeVerifier(
      typeSystem,
      diagnosticReporter,
      flowAnalysis,
    );
    elementResolver = ElementResolver(this);
    typeAnalyzer = StaticTypeAnalyzer(this);
    _functionReferenceResolver = FunctionReferenceResolver(this);
  }

  /// Inference context information for the current function body, if the
  /// current node is inside a function body.
  BodyInferenceContext? get bodyContext => _bodyContext;

  @override
  FlowAnalysis<
    AstNodeImpl,
    StatementImpl,
    ExpressionImpl,
    PromotableElementImpl,
    SharedTypeView
  >
  get flow => flowAnalysis.flow!;

  bool get isConstructorTearoffsEnabled =>
      _featureSet.isEnabled(Feature.constructor_tearoffs);

  bool get isInferenceUpdate1Enabled =>
      _featureSet.isEnabled(Feature.inference_update_1);

  /// Return the object providing promoted or declared types of variables.
  LocalVariableTypeProvider get localVariableTypeProvider {
    return flowAnalysis.localVariableTypeProvider;
  }

  @override
  shared.TypeAnalyzerOperations<
    PromotableElementImpl,
    InterfaceTypeImpl,
    InterfaceElementImpl
  >
  get operations => flowAnalysis.typeOperations;

  /// Gets the current depth of the [_rewriteStack].  This may be used in
  /// assertions to verify that pushes and pops are properly balanced.
  int get rewriteStackDepth => _rewriteStack.length;

  @override
  bool get strictCasts => analysisOptions.strictCasts;

  /// If a class, or mixin, is being resolved, the type of the class.
  ///
  /// If an extension is being resolved, the type of `this`, the declared
  /// extended type, or promoted.
  ///
  /// Otherwise `null`.
  TypeImpl? get thisType {
    return _thisType;
  }

  @override
  SharedTypeView analyzeExpression(
    ExpressionImpl node,
    SharedTypeSchemaView schema, {
    bool continueNullShorting = false,
  }) {
    inferenceLogWriter?.setExpressionVisitCodePath(
      node,
      ExpressionVisitCodePath.analyzeExpression,
    );
    return super.analyzeExpression(
      node,
      schema,
      continueNullShorting: continueNullShorting,
    );
  }

  List<SharedPatternField> buildSharedPatternFields(
    List<PatternFieldImpl> fields, {
    required bool mustBeNamed,
  }) {
    return fields.map((field) {
      Token? nameToken;
      var fieldName = field.name;
      if (fieldName != null) {
        nameToken = fieldName.name;
        if (nameToken == null) {
          var variablePattern = field.pattern.variablePattern;
          if (variablePattern != null) {
            variablePattern.fieldNameWithImplicitName = fieldName;
            nameToken = variablePattern.name;
          } else {
            diagnosticReporter.atNode(
              field,
              CompileTimeErrorCode.MISSING_NAMED_PATTERN_FIELD_NAME,
            );
          }
        }
      } else if (mustBeNamed) {
        diagnosticReporter.atNode(
          field,
          CompileTimeErrorCode.POSITIONAL_FIELD_IN_OBJECT_PATTERN,
        );
      }
      return shared.RecordPatternField(
        node: field,
        name: nameToken?.lexeme,
        pattern: field.pattern,
      );
    }).toList();
  }

  /// Verify that the arguments in the given [argumentList] can be assigned to
  /// their corresponding parameters.
  ///
  /// See [CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE].
  void checkForArgumentTypesNotAssignableInList(
    ArgumentListImpl argumentList,
    List<WhyNotPromotedGetter> whyNotPromotedArguments,
  ) {
    var arguments = argumentList.arguments;
    for (int i = 0; i < arguments.length; i++) {
      checkForArgumentTypeNotAssignableForArgument(
        arguments[i],
        whyNotPromoted:
            flowAnalysis.flow == null ? null : whyNotPromotedArguments[i],
      );
    }
  }

  void checkForBodyMayCompleteNormally({
    required FunctionBodyImpl body,
    required SyntacticEntity errorNode,
  }) {
    var bodyContext = body.bodyContext;
    if (bodyContext == null) {
      return;
    }

    if (!flowAnalysis.flow!.isReachable) {
      bodyContext.mayCompleteNormally = false;
      return;
    }

    var returnType = bodyContext.contextType;
    if (returnType == null) {
      if (errorNode is BlockFunctionBody) {
        _checkForFutureCatchErrorOnError(errorNode);
      }
      return;
    }

    if (body is BlockFunctionBody) {
      if (body.isGenerator) {
        return;
      }

      if (body.isAsynchronous) {
        // Check whether the return type is legal. If not, return rather than
        // reporting a second error.

        // This is the same check as [ReturnTypeVerifier._isLegalReturnType].
        // TODO(srawlins): When this check is moved into the resolution stage,
        // use the result of that check to determine whether this check should
        // be done.
        var lowerBound = typeProvider.futureElement2.instantiateImpl(
          typeArguments: fixedTypeList(NeverTypeImpl.instance),
          nullabilitySuffix: NullabilitySuffix.none,
        );
        var imposedType = bodyContext.imposedType;
        if (imposedType != null &&
            !typeSystem.isSubtypeOf(lowerBound, imposedType)) {
          // [imposedType] is an illegal return type for an asynchronous
          // non-generator function; do not report an additional error here.
          return;
        }
      }

      DiagnosticCode diagnosticCode;
      if (typeSystem.isPotentiallyNonNullable(returnType)) {
        diagnosticCode = CompileTimeErrorCode.BODY_MIGHT_COMPLETE_NORMALLY;
      } else {
        var returnTypeBase = typeSystem.futureOrBase(returnType);
        if (returnTypeBase is DynamicType ||
            returnTypeBase is InvalidType ||
            returnTypeBase is UnknownInferredType ||
            returnTypeBase is VoidType ||
            returnTypeBase.isDartCoreNull) {
          return;
        } else {
          diagnosticCode = WarningCode.BODY_MIGHT_COMPLETE_NORMALLY_NULLABLE;
        }
      }
      if (errorNode is ConstructorDeclaration) {
        diagnosticReporter.atConstructorDeclaration(
          errorNode,
          diagnosticCode,
          arguments: [returnType],
        );
      } else if (errorNode is BlockFunctionBody) {
        diagnosticReporter.atToken(
          errorNode.block.leftBracket,
          diagnosticCode,
          arguments: [returnType],
        );
      } else if (errorNode is Token) {
        diagnosticReporter.atToken(
          errorNode,
          diagnosticCode,
          arguments: [returnType],
        );
      }
    }
  }

  /// The client of the resolver should call this method after asking the
  /// resolver to visit an AST node.  This performs assertions to make sure that
  /// temporary resolver state has been properly cleaned up.
  void checkIdle() {
    assert(_rewriteStack.isEmpty);
    inferenceLogWriter?.assertIdle();
  }

  /// Reports an error if the [pattern] with the [requiredType] cannot
  /// match the [DartPatternImpl.matchedValueType].
  void checkPatternNeverMatchesValueType({
    required SharedMatchContext context,
    required DartPatternImpl pattern,
    required TypeImpl requiredType,
    required TypeImpl matchedValueType,
  }) {
    if (context.irrefutableContext == null) {
      if (!typeSystem.canBeSubtypeOf(matchedValueType, requiredType)) {
        AstNodeImpl? errorNode;
        if (pattern is CastPatternImpl) {
          errorNode = pattern.type;
        } else if (pattern is DeclaredVariablePatternImpl) {
          errorNode = pattern.type;
        } else if (pattern is ObjectPatternImpl) {
          errorNode = pattern.type;
        } else if (pattern is WildcardPatternImpl) {
          errorNode = pattern.type;
        }
        errorNode ??= pattern;
        diagnosticReporter.atNode(
          errorNode,
          WarningCode.PATTERN_NEVER_MATCHES_VALUE_TYPE,
          arguments: [matchedValueType, requiredType],
        );
      }
    }
  }

  void checkReadOfNotAssignedLocalVariable(
    SimpleIdentifier node,
    Element? element,
  ) {
    if (flowAnalysis.flow == null) {
      return;
    }

    if (!node.inGetterContext()) {
      return;
    }

    if (element is PromotableElementImpl) {
      var assigned = flowAnalysis.isDefinitelyAssigned(node, element);
      var unassigned = flowAnalysis.isDefinitelyUnassigned(node, element);

      if (element.isLate) {
        if (unassigned) {
          diagnosticReporter.atNode(
            node,
            CompileTimeErrorCode.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE,
            arguments: [node.name],
          );
        }
        return;
      }

      if (!assigned) {
        if (element.isFinal) {
          diagnosticReporter.atNode(
            node,
            CompileTimeErrorCode.READ_POTENTIALLY_UNASSIGNED_FINAL,
            arguments: [node.name],
          );
          return;
        }

        if (typeSystem.isPotentiallyNonNullable(element.type)) {
          diagnosticReporter.atNode(
            node,
            CompileTimeErrorCode
                .NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE,
            arguments: [node.name],
          );
          return;
        }
      }
    }
  }

  void checkUnreachableNode(AstNode node) {
    nullSafetyDeadCodeVerifier.visitNode(node);
  }

  @override
  List<DiagnosticMessage> computeWhyNotPromotedMessages(
    SyntacticEntity errorEntity,
    Map<SharedTypeView, NonPromotionReason>? whyNotPromoted,
  ) {
    List<DiagnosticMessage> messages = [];
    if (whyNotPromoted != null) {
      for (var entry in whyNotPromoted.entries) {
        var whyNotPromotedVisitor = _WhyNotPromotedVisitor(
          source,
          errorEntity,
          flowAnalysis.dataForTesting,
        );
        if (typeSystem.isPotentiallyNullable(
          // TODO(paulberry): make this type argument unnecessary by changing
          // the parameter of `TypeSystemImpl.isPotentiallyNullable` to
          // (covariant) `TypeImpl`.
          entry.key.unwrapTypeView<TypeImpl>(),
        )) {
          continue;
        }
        messages = entry.value.accept(whyNotPromotedVisitor);
        // `messages` will be passed to the DiagnosticReporter, which might add
        // additional entries. So make sure that it's not a `const []`.
        assert(_isModifiableList(messages));
        if (messages.isNotEmpty) {
          if (flowAnalysis.dataForTesting != null) {
            var nonPromotionReasonText = entry.value.shortName;
            var args = <String>[];
            var propertyReference = whyNotPromotedVisitor.propertyReference;
            if (propertyReference != null) {
              var id = computeMemberId(propertyReference);
              args.add('target: $id');
            }
            if (args.isNotEmpty) {
              nonPromotionReasonText += '(${args.join(', ')})';
            }
            flowAnalysis.dataForTesting!.nonPromotionReasons[errorEntity] =
                nonPromotionReasonText;
          }
        }
        break;
      }
    }
    return messages;
  }

  @override
  void dispatchCollectionElement(
    covariant CollectionElementImpl element,
    covariant CollectionLiteralContext? context,
  ) {
    element.resolveElement(this, context);
    popRewrite();
  }

  @override
  ExpressionTypeAnalysisResult dispatchExpression(
    covariant ExpressionImpl expression,
    SharedTypeSchemaView context,
  ) {
    int? stackDepth;
    assert(() {
      stackDepth = rewriteStackDepth;
      return true;
    }());
    // TODO(paulberry): implement null shorting
    // Stack: ()
    pushRewrite(expression);
    // Stack: (Expression)
    expression.resolveExpression(this, context.unwrapTypeSchemaView());
    inferenceLogWriter?.assertExpressionWasRecorded(expression);
    assert(rewriteStackDepth == stackDepth! + 1);
    var replacementExpression = peekRewrite()!;
    assert(
      identical(_replacements[expression] ?? expression, replacementExpression),
    );
    var staticType = replacementExpression.staticType;
    if (staticType == null) {
      var shouldHaveType = true;
      if (replacementExpression is ExtensionOverride) {
        shouldHaveType = false;
      } else if (replacementExpression is IdentifierImpl) {
        var element = replacementExpression.element;
        if (element is ExtensionElement ||
            element is InterfaceElement ||
            element is PrefixElement ||
            element is TypeAliasElement) {
          shouldHaveType = false;
        }
      }
      if (shouldHaveType) {
        assert(
          false,
          'No static type for: '
          '(${replacementExpression.runtimeType}) $replacementExpression',
        );
      }
      staticType = operations.unknownType.unwrapTypeSchemaView();
    }
    return ExpressionTypeAnalysisResult(type: SharedTypeView(staticType));
  }

  @override
  PatternResult dispatchPattern(SharedMatchContext context, AstNodeImpl node) {
    shared.PatternResult analysisResult;
    if (node is DartPatternImpl) {
      analysisResult = node.resolvePattern(this, context);
      node.matchedValueType = analysisResult.matchedValueType.unwrapTypeView();
    } else {
      // This can occur inside conventional switch statements, since
      // [SwitchCase] points directly to an [Expression] rather than to a
      // [ConstantPattern].  So we mimic what
      // [ConstantPatternImpl.resolvePattern] would do.
      analysisResult = analyzeConstantPattern(
        context,
        node,
        node as ExpressionImpl,
      );
      // Stack: (Expression)
      popRewrite();
      // Stack: ()
    }
    return analysisResult;
  }

  @override
  SharedTypeSchemaView dispatchPatternSchema(covariant DartPatternImpl node) {
    return SharedTypeSchemaView(node.computePatternSchema(this));
  }

  @override
  void dispatchStatement(Statement statement) {
    statement.accept(this);
  }

  @override
  SharedTypeView downwardInferObjectPatternRequiredType({
    required SharedTypeView matchedType,
    required covariant ObjectPatternImpl pattern,
  }) {
    var typeNode = pattern.type;
    if (typeNode.typeArguments == null) {
      var typeNameElement = typeNode.element2;
      if (typeNameElement is InterfaceElementImpl) {
        var typeParameters = typeNameElement.typeParameters2;
        if (typeParameters.isNotEmpty) {
          var typeArguments = _inferTypeArguments(
            typeParameters: typeParameters,
            errorNode: typeNode,
            declaredType: typeNameElement.thisType,
            contextType: matchedType.unwrapTypeView(),
            nodeForTesting: pattern,
          );
          return SharedTypeView(
            typeNode.type = typeNameElement.instantiateImpl(
              typeArguments: typeArguments,
              nullabilitySuffix: NullabilitySuffix.none,
            ),
          );
        }
      } else if (typeNameElement is TypeAliasElementImpl) {
        var typeParameters = typeNameElement.typeParameters2;
        if (typeParameters.isNotEmpty) {
          var typeArguments = _inferTypeArguments(
            typeParameters: typeParameters,
            errorNode: typeNode,
            declaredType: typeNameElement.aliasedType,
            contextType: matchedType.unwrapTypeView(),
            nodeForTesting: pattern,
          );
          return SharedTypeView(
            typeNode.type = typeNameElement.instantiateImpl(
              typeArguments: typeArguments,
              nullabilitySuffix: NullabilitySuffix.none,
            ),
          );
        }
      }
    }
    return SharedTypeView(typeNode.typeOrThrow);
  }

  @override
  void finishExpressionCase(
    covariant SwitchExpressionImpl node,
    int caseIndex,
  ) {
    var case_ = node.cases[caseIndex];
    case_.expression = popRewrite()!;
    nullSafetyDeadCodeVerifier.flowEnd(case_);
  }

  @override
  void finishJoinedPatternVariable(
    covariant JoinPatternVariableElementImpl variable, {
    required JoinedPatternVariableLocation location,
    required shared.JoinedPatternVariableInconsistency inconsistency,
    required bool isFinal,
    required SharedTypeView type,
  }) {
    variable.inconsistency = variable.inconsistency.maxWith(inconsistency);
    variable.isFinal = isFinal;
    variable.type = type.unwrapTypeView();

    if (location == JoinedPatternVariableLocation.sharedCaseScope) {
      for (var reference in variable.references) {
        if (variable.inconsistency ==
            shared.JoinedPatternVariableInconsistency.sharedCaseAbsent) {
          diagnosticReporter.atNode(
            reference,
            CompileTimeErrorCode
                .PATTERN_VARIABLE_SHARED_CASE_SCOPE_NOT_ALL_CASES,
            arguments: [variable.name3!],
          );
        } else if (variable.inconsistency ==
            shared.JoinedPatternVariableInconsistency.sharedCaseHasLabel) {
          diagnosticReporter.atNode(
            reference,
            CompileTimeErrorCode.PATTERN_VARIABLE_SHARED_CASE_SCOPE_HAS_LABEL,
            arguments: [variable.name3!],
          );
        } else if (variable.inconsistency ==
            shared.JoinedPatternVariableInconsistency.differentFinalityOrType) {
          diagnosticReporter.atNode(
            reference,
            CompileTimeErrorCode
                .PATTERN_VARIABLE_SHARED_CASE_SCOPE_DIFFERENT_FINALITY_OR_TYPE,
            arguments: [variable.name3!],
          );
        }
      }
    }
  }

  @override
  shared.MapPatternEntry<ExpressionImpl, DartPatternImpl>? getMapPatternEntry(
    covariant MapPatternElementImpl element,
  ) {
    if (element is MapPatternEntryImpl) {
      return shared.MapPatternEntry(key: element.key, value: element.value);
    }
    return null;
  }

  @override
  DartPatternImpl? getRestPatternElementPattern(
    covariant RestPatternElementImpl element,
  ) {
    return element.pattern;
  }

  @override
  SwitchExpressionMemberInfo<AstNodeImpl, ExpressionImpl, PromotableElementImpl>
  getSwitchExpressionMemberInfo(
    covariant SwitchExpressionImpl node,
    int index,
  ) {
    var case_ = node.cases[index];
    var guardedPattern = case_.guardedPattern;
    return SwitchExpressionMemberInfo(
      head: CaseHeadOrDefaultInfo(
        pattern: guardedPattern.pattern,
        guard: guardedPattern.whenClause?.expression,
        variables: guardedPattern.variables,
      ),
      expression: case_.expression,
    );
  }

  @override
  SwitchStatementMemberInfo<
    AstNodeImpl,
    StatementImpl,
    ExpressionImpl,
    PromotableElementImpl
  >
  getSwitchStatementMemberInfo(covariant SwitchStatementImpl node, int index) {
    CaseHeadOrDefaultInfo<AstNodeImpl, ExpressionImpl, PromotableElementImpl>
    ofMember(SwitchMemberImpl member) {
      if (member is SwitchCaseImpl) {
        return CaseHeadOrDefaultInfo(pattern: member.expression, variables: {});
      } else if (member is SwitchPatternCaseImpl) {
        var guardedPattern = member.guardedPattern;
        return CaseHeadOrDefaultInfo(
          pattern: guardedPattern.pattern,
          variables: guardedPattern.variables,
          guard: guardedPattern.whenClause?.expression,
        );
      } else {
        return CaseHeadOrDefaultInfo(pattern: null, variables: {});
      }
    }

    var group = node.memberGroups[index];
    return SwitchStatementMemberInfo(
      heads: group.members.map(ofMember).toList(),
      body: group.statements,
      variables: group.variables,
      hasLabels: group.hasLabels,
    );
  }

  @override
  void handle_ifElement_conditionEnd(covariant IfElementImpl node) {
    // Stack: (Expression condition)
    var condition = popRewrite()!;

    var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(condition);
    boolExpressionVerifier.checkForNonBoolCondition(
      condition,
      whyNotPromoted: whyNotPromoted,
    );
  }

  @override
  void handle_ifElement_elseEnd(
    covariant IfElementImpl node,
    covariant CollectionElementImpl ifFalse,
  ) {
    nullSafetyDeadCodeVerifier.flowEnd(ifFalse);
  }

  @override
  void handle_ifElement_thenEnd(
    covariant IfElementImpl node,
    covariant CollectionElementImpl ifTrue,
  ) {
    nullSafetyDeadCodeVerifier.flowEnd(ifTrue);
  }

  @override
  void handle_ifStatement_conditionEnd(Statement node) {
    // Stack: (Expression condition)
    var condition = popRewrite()!;

    var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(condition);
    boolExpressionVerifier.checkForNonBoolCondition(
      condition,
      whyNotPromoted: whyNotPromoted,
    );
  }

  @override
  void handle_ifStatement_elseEnd(Statement node, Statement ifFalse) {
    nullSafetyDeadCodeVerifier.flowEnd(ifFalse);
  }

  @override
  void handle_ifStatement_thenEnd(Statement node, Statement ifTrue) {
    nullSafetyDeadCodeVerifier.flowEnd(ifTrue);
  }

  @override
  void handle_logicalOrPattern_afterLhs(covariant LogicalOrPatternImpl node) {
    checkUnreachableNode(node.rightOperand);
  }

  @override
  void handleCase_afterCaseHeads(
    AstNode node,
    int caseIndex,
    Iterable<PromotableElement> variables,
  ) {}

  @override
  void handleCaseHead(
    covariant AstNodeImpl node, {
    required int caseIndex,
    required int subIndex,
  }) {
    // Stack: (Expression)
    popRewrite(); // "when" expression
    // Stack: ()
    if (node is SwitchStatementImpl) {
      var group = node.memberGroups[caseIndex];
      legacySwitchExhaustiveness?.visitSwitchMember(group);
      nullSafetyDeadCodeVerifier.flowEnd(group.members[subIndex]);
    } else if (node is SwitchExpressionImpl) {
      legacySwitchExhaustiveness?.visitSwitchExpressionCase(
        node.cases[caseIndex],
      );
    }
  }

  @override
  void handleDefault(
    covariant SwitchStatementImpl node, {
    required int caseIndex,
    required int subIndex,
  }) {
    var group = node.memberGroups[caseIndex];
    legacySwitchExhaustiveness?.visitSwitchMember(group);
    nullSafetyDeadCodeVerifier.flowEnd(group.members[subIndex]);
  }

  @override
  void handleListPatternRestElement(
    DartPattern container,
    covariant RestPatternElementImpl restElement,
  ) {}

  @override
  void handleMapPatternEntry(
    DartPattern container,
    covariant MapPatternEntryImpl entry,
    SharedTypeView keyType,
  ) {
    entry.key = popRewrite()!;
  }

  @override
  void handleMapPatternRestElement(
    DartPattern container,
    covariant RestPatternElementImpl restElement,
  ) {}

  @override
  void handleMergedStatementCase(
    covariant SwitchStatementImpl node, {
    required int caseIndex,
    required bool isTerminating,
  }) {
    nullSafetyDeadCodeVerifier.flowEnd(
      node.memberGroups[caseIndex].members.last,
    );
  }

  @override
  void handleNoCollectionElement(AstNode node) {}

  @override
  void handleNoGuard(AstNode node, int caseIndex) {
    // Stack: ()
    // We can push `null` here because there is no actual expression associated
    // with the lack of a guard, so there's nothing that will need rewriting.
    pushRewrite(null);
    // Stack: (Expression)
  }

  @override
  void handleNoStatement(Statement node) {}

  @override
  void handleSwitchBeforeAlternative(
    covariant AstNodeImpl node, {
    required int caseIndex,
    required int subIndex,
  }) {
    if (node is SwitchExpressionImpl) {
      var case_ = node.cases[caseIndex];
      checkUnreachableNode(case_);
    } else if (node is SwitchStatementImpl) {
      var member = node.memberGroups[caseIndex].members[subIndex];
      checkUnreachableNode(member);
    }
  }

  @override
  void handleSwitchScrutinee(SharedTypeView type) {
    if (!typeAnalyzerOptions.patternsEnabled) {
      legacySwitchExhaustiveness = SwitchExhaustiveness(type.unwrapTypeView());
    }
  }

  /// If generic function instantiation should be performed on `expression`,
  /// inserts a [FunctionReference] node which wraps [expression].
  ///
  /// If an [FunctionReference] is inserted, returns it; otherwise, returns
  /// [expression].
  ExpressionImpl insertGenericFunctionInstantiation(
    Expression expression, {
    required TypeImpl contextType,
  }) {
    expression as ExpressionImpl;
    if (!isConstructorTearoffsEnabled) {
      // Temporarily, only create [ImplicitCallReference] nodes under the
      // 'constructor-tearoffs' feature.
      // TODO(srawlins): When we are ready to make a breaking change release to
      // the analyzer package, remove this exception.
      return expression;
    }

    // Don't rewrite function declarations.
    if (expression.parent is FunctionDeclaration) {
      return expression;
    }

    var staticType = expression.staticType;
    if (staticType is! FunctionTypeImpl || staticType.typeFormals.isEmpty) {
      return expression;
    }

    var context = typeSystem.flatten(contextType);
    if (context is! FunctionTypeImpl || context.typeFormals.isNotEmpty) {
      return expression;
    }

    var typeArgumentTypes = typeSystem.inferFunctionTypeInstantiation(
      context,
      staticType,
      diagnosticReporter: diagnosticReporter,
      errorNode: expression,
      // If the constructor-tearoffs feature is enabled, then so is
      // generic-metadata.
      genericMetadataIsEnabled: true,
      inferenceUsingBoundsIsEnabled: inferenceUsingBoundsIsEnabled,
      strictInference: analysisOptions.strictInference,
      strictCasts: analysisOptions.strictCasts,
      typeSystemOperations: flowAnalysis.typeOperations,
      dataForTesting: inferenceHelper.dataForTesting,
      nodeForTesting: expression,
    );
    if (typeArgumentTypes.isNotEmpty) {
      staticType = staticType.instantiate(typeArgumentTypes);
    }

    var parent = expression.parent;
    var genericFunctionInstantiation = FunctionReferenceImpl(
      function: expression,
      typeArguments: null,
    );
    replaceExpression(expression, genericFunctionInstantiation, parent: parent);

    genericFunctionInstantiation.typeArgumentTypes = typeArgumentTypes;
    genericFunctionInstantiation.setPseudoExpressionStaticType(staticType);

    return genericFunctionInstantiation;
  }

  @override
  bool isDotShorthand(ExpressionImpl node) {
    if (node is DotShorthandMixin) {
      return node.isDotShorthand;
    }
    return false;
  }

  @override
  bool isLegacySwitchExhaustive(AstNode node, SharedTypeView expressionType) =>
      legacySwitchExhaustiveness!.isExhaustive;

  @override
  bool isRestPatternElement(AstNode node) {
    return node is RestPatternElementImpl;
  }

  @override
  bool isVariablePattern(AstNode pattern) => pattern is DeclaredVariablePattern;

  /// If we reached a null-shorting termination, and the [node] has null
  /// shorting, make the type of the [node] nullable.
  ///
  /// [node] should be the original expression node (before resolution). If the
  /// resolution process rewrote [node] to some other expression, that
  /// expression should be passed in as [rewrittenExpression].
  void nullShortingTermination(
    ExpressionImpl node, {
    ExpressionImpl? rewrittenExpression,
  }) {
    // Verify that `rewrittenExpression` properly reflects any rewrites that
    // were performed on `node`.
    assert(identical(rewrittenExpression ?? node, _replacements[node] ?? node));

    if (identical(_unfinishedNullShorts.last, node)) {
      do {
        _unfinishedNullShorts.removeLast();
        flowAnalysis.flow!.nullAwareAccess_end();
        nullSafetyDeadCodeVerifier.flowEnd(node);
      } while (identical(_unfinishedNullShorts.last, node));
      if (node is! CascadeExpression) {
        // Make the static type of `node` (or whatever it was rewritten to)
        // nullable.
        rewrittenExpression ??= node;
        rewrittenExpression.setPseudoExpressionStaticType(
          typeSystem.makeNullable(rewrittenExpression.typeOrThrow),
        );
      }
    }
  }

  /// If it is appropriate to do so, override the current type of the static
  /// element associated with the given expression with the given type.
  /// Generally speaking, it is appropriate if the given type is more specific
  /// than the current type.
  ///
  /// @param expression the expression used to access the static element whose
  ///        types might be overridden
  /// @param potentialType the potential type of the elements
  /// @param allowPrecisionLoss see @{code overrideVariable} docs
  void overrideExpression(
    Expression expression,
    DartType potentialType,
    bool allowPrecisionLoss,
    bool setExpressionType,
  ) {
    // TODO(brianwilkerson): Remove this method.
  }

  /// Examines the top entry of [_rewriteStack] but does not pop it.
  ExpressionImpl? peekRewrite() => _rewriteStack.last;

  /// Pops the top entry off of [_rewriteStack].
  ExpressionImpl? popRewrite() {
    var expression = _rewriteStack.removeLast();
    if (_debugRewriteStack) {
      assert(_debugPrint('POP ${expression.runtimeType} $expression'));
    }
    return expression;
  }

  /// Set information about enclosing declarations.
  void prepareEnclosingDeclarations({
    InterfaceElementImpl? enclosingClassElement,
    ExecutableElementImpl? enclosingExecutableElement,
  }) {
    enclosingClass = enclosingClassElement;
    _setupThisType();
    enclosingFunction = enclosingExecutableElement;
  }

  /// We are going to resolve [node], without visiting its parent.
  /// Do necessary preparations - set enclosing elements, scopes, etc.
  /// This [ResolverVisitor] instance is fresh, just created.
  ///
  /// Return `true` if we were able to do this, or `false` if it is not
  /// possible to resolve only [node].
  bool prepareForResolving(AstNode node) {
    var parent = node.parent;

    if (parent is CompilationUnit) {
      return node is ClassDeclaration ||
          node is Directive ||
          node is ExtensionDeclaration ||
          node is FunctionDeclaration ||
          node is TopLevelVariableDeclaration;
    }

    if (parent is ClassDeclarationImpl) {
      enclosingClass = parent.declaredFragment!.element;
      return true;
    }

    if (parent is ExtensionDeclarationImpl) {
      enclosingExtension = parent.declaredFragment!.element;
      return true;
    }

    if (parent is MixinDeclarationImpl) {
      enclosingClass = parent.declaredFragment!.element;
      return true;
    }

    return false;
  }

  /// Pushes an entry onto [_rewriteStack].
  void pushRewrite(ExpressionImpl? expression) {
    if (_debugRewriteStack) {
      assert(_debugPrint('PUSH ${expression.runtimeType} $expression'));
    }
    _rewriteStack.add(expression);
  }

  /// Replaces the expression [oldNode] with [newNode], updating the node's
  /// parent as appropriate.
  ///
  /// If [newNode] is the parent of [oldNode] already (because [newNode] became
  /// the parent of [oldNode] in its constructor), this action will loop
  /// infinitely; pass [oldNode]'s previous parent as [parent] to avoid this.
  void replaceExpression(
    Expression oldNode,
    ExpressionImpl newNode, {
    AstNode? parent,
  }) {
    assert(() {
      assert(_replacements[oldNode] == null);
      _replacements[oldNode] = newNode;
      return true;
    }());
    if (_rewriteStack.isNotEmpty && identical(peekRewrite(), oldNode)) {
      if (_debugRewriteStack) {
        assert(_debugPrint('REPLACE ${newNode.runtimeType} $newNode'));
      }
      _rewriteStack.last = newNode;
    }
    inferenceLogWriter?.recordExpressionRewrite(
      oldExpression: oldNode,
      newExpression: newNode,
    );
    NodeReplacer.replace(oldNode, newNode, parent: parent);
    nullSafetyDeadCodeVerifier.maybeRewriteFirstDeadNode(oldNode, newNode);
  }

  PatternResult resolveAssignedVariablePattern({
    required AssignedVariablePatternImpl node,
    required SharedMatchContext context,
  }) {
    var element = node.element2;
    if (element is! PromotableElementImpl) {
      return PatternResult(
        matchedValueType: SharedTypeView(InvalidTypeImpl.instance),
      );
    }

    if (element.isFinal) {
      var flow = this.flow;
      if (element.isLate) {
        if (flow.isAssigned(element)) {
          diagnosticReporter.atToken(
            node.name,
            CompileTimeErrorCode.LATE_FINAL_LOCAL_ALREADY_ASSIGNED,
          );
        }
      } else {
        if (!flow.isUnassigned(element)) {
          diagnosticReporter.atToken(
            node.name,
            CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_LOCAL,
            arguments: [node.name.lexeme],
          );
        }
      }
    }

    return analyzeAssignedVariablePattern(context, node, element);
  }

  /// Resolve LHS [node] of an assignment, an explicit [AssignmentExpression],
  /// or implicit [PrefixExpression] or [PostfixExpression].
  PropertyElementResolverResult resolveForWrite({
    required ExpressionImpl node,
    required bool hasRead,
  }) {
    inferenceLogWriter?.enterLValue(node);
    if (node is IndexExpressionImpl) {
      var target = node.target;
      if (target != null) {
        if (isDotShorthand(node)) {
          // Recovery.
          // It's a compile-time error to use postfix or prefix operators with
          // dot shorthands. We provide an unknown type since this shouldn't be
          // valid code, but we want to prevent any crashes.
          pushDotShorthandContext(target, operations.unknownType);
        }
        analyzeExpression(target, operations.unknownType);
        popRewrite();
      }

      if (node.isNullAware) {
        _startNullAwareAccess(node, node.target);
        nullSafetyDeadCodeVerifier.visitNode(node.index);
      }

      var result = _propertyElementResolver.resolveIndexExpression(
        node: node,
        hasRead: hasRead,
        hasWrite: true,
      );

      analyzeExpression(
        node.index,
        SharedTypeSchemaView(result.indexContextType),
      );
      popRewrite();
      var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(node.index);
      checkIndexExpressionIndex(
        node.index,
        readElement:
            hasRead ? result.readElement2 as ExecutableElement2OrMember? : null,
        writeElement: result.writeElement2 as ExecutableElement2OrMember?,
        whyNotPromoted: whyNotPromoted,
      );

      inferenceLogWriter?.exitLValue(node);
      return result;
    } else if (node is PrefixedIdentifierImpl) {
      var prefix = node.prefix;
      analyzeExpression(prefix, operations.unknownType);
      popRewrite();

      // TODO(scheglov): It would be nice to rewrite all such cases.
      if (prefix.staticType is RecordType) {
        var propertyAccess = PropertyAccessImpl(
          target: prefix,
          operator: node.period,
          propertyName: node.identifier,
        );
        NodeReplacer.replace(node, propertyAccess);
        inferenceLogWriter?.exitLValue(node);
        return _propertyElementResolver.resolvePropertyAccess(
          node: propertyAccess,
          hasRead: hasRead,
          hasWrite: true,
        );
      }

      inferenceLogWriter?.exitLValue(node);
      return _propertyElementResolver.resolvePrefixedIdentifier(
        node: node,
        hasRead: hasRead,
        hasWrite: true,
      );
    } else if (node is PropertyAccessImpl) {
      if (node.target case var target?) {
        analyzeExpression(target, operations.unknownType);
        popRewrite();
      }
      if (node.isNullAware) {
        _startNullAwareAccess(node, node.target);
        nullSafetyDeadCodeVerifier.visitNode(node.propertyName);
      }

      inferenceLogWriter?.exitLValue(node);
      return _propertyElementResolver.resolvePropertyAccess(
        node: node,
        hasRead: hasRead,
        hasWrite: true,
      );
    } else if (node is SimpleIdentifierImpl) {
      var result = _propertyElementResolver.resolveSimpleIdentifier(
        node: node,
        hasRead: hasRead,
        hasWrite: true,
      );

      if (hasRead && result.readElementRequested2 == null) {
        diagnosticReporter.atNode(
          node,
          CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
          arguments: [node.name],
        );
      }

      inferenceLogWriter?.exitLValue(node);
      return result;
    } else {
      inferenceLogWriter?.exitLValue(node, reanalyzeAsRValue: true);
      analyzeExpression(
        node,
        SharedTypeSchemaView(UnknownInferredType.instance),
      );
      popRewrite();
      return PropertyElementResolverResult();
    }
  }

  PatternResult resolveMapPattern({
    required MapPatternImpl node,
    required SharedMatchContext context,
  }) {
    inferenceLogWriter?.enterPattern(node);
    ({SharedTypeView keyType, SharedTypeView valueType})? typeArguments;
    var typeArgumentsList = node.typeArguments;
    if (typeArgumentsList != null) {
      typeArgumentsList.accept(this);
      // Check that we have exactly two type arguments.
      var length = typeArgumentsList.arguments.length;
      if (length == 2) {
        typeArguments = (
          keyType: SharedTypeView(typeArgumentsList.arguments[0].typeOrThrow),
          valueType: SharedTypeView(typeArgumentsList.arguments[1].typeOrThrow),
        );
      } else {
        diagnosticReporter.atNode(
          typeArgumentsList,
          CompileTimeErrorCode.EXPECTED_TWO_MAP_PATTERN_TYPE_ARGUMENTS,
          arguments: [length],
        );
      }
    }

    var result = analyzeMapPattern(
      context,
      node,
      typeArguments: typeArguments,
      elements: node.elements,
    );
    node.requiredType = result.requiredType.unwrapTypeView();

    checkPatternNeverMatchesValueType(
      context: context,
      pattern: node,
      requiredType: result.requiredType.unwrapTypeView(),
      matchedValueType: result.matchedValueType.unwrapTypeView(),
    );
    inferenceLogWriter?.exitPattern(node);

    return result;
  }

  @override
  (ExecutableElement?, SharedTypeView) resolveObjectPatternPropertyGet({
    required covariant ObjectPatternImpl objectPattern,
    required SharedTypeView receiverType,
    required covariant SharedPatternField field,
  }) {
    var fieldNode = field.node;
    var nameToken = fieldNode.name?.name;
    nameToken ??= field.pattern.variablePattern?.name;
    if (nameToken == null) {
      return (null, SharedTypeView(typeProvider.dynamicType));
    }

    var result = typePropertyResolver.resolve(
      receiver: null,
      receiverType: receiverType.unwrapTypeView(),
      name: nameToken.lexeme,
      hasRead: true,
      hasWrite: false,
      propertyErrorEntity: objectPattern.type,
      nameErrorEntity: nameToken,
    );

    if (result.needsGetterError) {
      diagnosticReporter.atToken(
        nameToken,
        CompileTimeErrorCode.UNDEFINED_GETTER,
        arguments: [nameToken.lexeme, receiverType],
      );
    }

    var getter = result.getter2;
    if (getter != null) {
      fieldNode.element2 = getter;
      if (getter is PropertyAccessorElement2OrMember) {
        return (getter, SharedTypeView(getter.returnType));
      } else {
        return (getter, SharedTypeView(getter.type));
      }
    }

    var recordField = result.recordField;
    if (recordField != null) {
      return (null, SharedTypeView(recordField.type));
    }

    return (null, SharedTypeView(typeProvider.dynamicType));
  }

  @override
  RelationalOperatorResolution? resolveRelationalPatternOperator(
    covariant RelationalPatternImpl node,
    SharedTypeView matchedType,
  ) {
    var operatorLexeme = node.operator.lexeme;
    RelationalOperatorKind kind;
    String methodName;
    if (operatorLexeme == '==') {
      kind = RelationalOperatorKind.equals;
      methodName = '==';
    } else if (operatorLexeme == '!=') {
      kind = RelationalOperatorKind.notEquals;
      methodName = '==';
    } else {
      kind = RelationalOperatorKind.other;
      methodName = operatorLexeme;
    }

    var result = typePropertyResolver.resolve(
      receiver: null,
      receiverType: matchedType.unwrapTypeView(),
      name: methodName,
      hasRead: true,
      hasWrite: false,
      propertyErrorEntity: node.operator,
      nameErrorEntity: node,
      parentNode: node,
    );

    if (result.needsGetterError) {
      diagnosticReporter.atToken(
        node.operator,
        CompileTimeErrorCode.UNDEFINED_OPERATOR,
        arguments: [methodName, matchedType],
      );
    }

    var element = result.getter2 as MethodElement2OrMember?;
    node.element2 = element;
    if (element == null) {
      return null;
    }

    var parameterType = element.firstParameterType;
    if (parameterType == null) {
      return null;
    }

    return RelationalOperatorResolution(
      kind: kind,
      parameterType: SharedTypeView(parameterType),
      returnType: SharedTypeView(element.returnType),
    );
  }

  void setReadElement(
    Expression node,
    Element? element, {
    required bool atDynamicTarget,
  }) {
    var readType =
        atDynamicTarget ? DynamicTypeImpl.instance : InvalidTypeImpl.instance;
    if (node is IndexExpression) {
      if (element is MethodElement2OrMember) {
        readType = element.returnType;
      }
    } else if (node is PrefixedIdentifier ||
        node is PropertyAccess ||
        node is SimpleIdentifier) {
      if (element is GetterElement2OrMember) {
        readType = element.returnType;
      } else if (element is VariableElement) {
        readType = localVariableTypeProvider.getType(
          node as SimpleIdentifierImpl,
          isRead: true,
        );
      }
    }

    var parent = node.parent;
    if (parent is AssignmentExpressionImpl && parent.leftHandSide == node) {
      parent.readElement2 = element;
      parent.readType = readType;
    } else if (parent is PostfixExpressionImpl &&
        parent.operator.type.isIncrementOperator) {
      parent.readElement2 = element;
      parent.readType = readType;
    } else if (parent is PrefixExpressionImpl &&
        parent.operator.type.isIncrementOperator) {
      parent.readElement2 = element;
      parent.readType = readType;
    }
  }

  @override
  void setVariableType(PromotableElement variable, SharedTypeView type) {
    if (variable is LocalVariableElementImpl) {
      variable.type = type.unwrapTypeView();
    } else {
      throw UnimplementedError('TODO(paulberry)');
    }
  }

  void setWriteElement(
    Expression node,
    Element? element, {
    required bool atDynamicTarget,
  }) {
    var writeType =
        atDynamicTarget ? DynamicTypeImpl.instance : InvalidTypeImpl.instance;
    if (node is AugmentedExpression) {
      if (element is SetterElement2OrMember) {
        if (element.formalParameters case [var valueParameter]) {
          writeType = valueParameter.type;
        }
      }
    } else if (node is IndexExpression) {
      if (element is MethodElement2OrMember) {
        var parameters = element.formalParameters;
        if (parameters.length == 2) {
          writeType = parameters[1].type;
        }
      }
    } else if (node is PrefixedIdentifier ||
        node is PropertyAccess ||
        node is SimpleIdentifier) {
      if (element is SetterElement2OrMember) {
        if (element.isSynthetic) {
          var variable = element.variable3;
          if (variable != null) {
            writeType = variable.type;
          }
        } else {
          var parameters = element.formalParameters;
          if (parameters.length == 1) {
            writeType = parameters[0].type;
          }
        }
      } else if (element is VariableElement2OrMember) {
        writeType = element.type;
      }
    }

    var parent = node.parent;
    if (parent is AssignmentExpressionImpl && parent.leftHandSide == node) {
      parent.writeElement2 = element;
      parent.writeType = writeType;
    } else if (parent is PostfixExpressionImpl &&
        parent.operator.type.isIncrementOperator) {
      parent.writeElement2 = element;
      parent.writeType = writeType;
    } else if (parent is PrefixExpressionImpl &&
        parent.operator.type.isIncrementOperator) {
      parent.writeElement2 = element;
      parent.writeType = writeType;
    }
  }

  /// Returns the result of an implicit `this.` lookup for the identifier [node]
  /// in a getter context, or `null` if no match was found.
  LexicalLookupResult? thisLookupGetter(SimpleIdentifier node) {
    return ThisLookup.lookupGetter(this, node);
  }

  /// Returns the result of an implicit `this.` lookup for the identifier [node]
  /// in a setter context, or `null` if no match was found.
  LexicalLookupResult? thisLookupSetter(SimpleIdentifier node) {
    return ThisLookup.lookupSetter(this, node);
  }

  @override
  SharedTypeView variableTypeFromInitializerType(SharedTypeView type) {
    TypeImpl unwrapped = type.unwrapTypeView();
    if (unwrapped.isDartCoreNull) {
      return SharedTypeView(DynamicTypeImpl.instance);
    }
    return SharedTypeView(typeSystem.demoteType(unwrapped));
  }

  @override
  void visitAdjacentStrings(
    covariant AdjacentStringsImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    for (var string in node.strings) {
      analyzeExpression(string, operations.unknownType);
      popRewrite();
    }
    typeAnalyzer.visitAdjacentStrings(node);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitAnnotation(covariant AnnotationImpl node) {
    inferenceLogWriter?.enterAnnotation(node);
    // Annotations can contain expressions, so we need flow analysis to be
    // available to process those expressions.
    var isTopLevel = flowAnalysis.flow == null;
    if (isTopLevel) {
      flowAnalysis.bodyOrInitializer_enter(node, null);
    }
    assert(flowAnalysis.flow != null);
    var whyNotPromotedArguments =
        <Map<SharedTypeView, NonPromotionReason> Function()>[];
    _annotationResolver.resolve(node, whyNotPromotedArguments);
    var arguments = node.arguments;
    if (arguments != null) {
      checkForArgumentTypesNotAssignableInList(
        arguments,
        whyNotPromotedArguments,
      );
    }
    if (isTopLevel) {
      flowAnalysis.bodyOrInitializer_exit();
    }
    inferenceLogWriter?.exitAnnotation(node);
  }

  @override
  void visitAsExpression(
    covariant AsExpressionImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);

    analyzeExpression(
      node.expression,
      SharedTypeSchemaView(UnknownInferredType.instance),
    );
    popRewrite();

    checkUnreachableNode(node.type);
    node.type.accept(this);

    typeAnalyzer.visitAsExpression(node);
    flowAnalysis.asExpression(node);
    _insertImplicitCallReference(
      insertGenericFunctionInstantiation(node, contextType: contextType),
      contextType: contextType,
    );

    var expression = node.expression;
    var staticType = node.staticType;
    if (staticType != null && expression is SimpleIdentifier) {
      var simpleIdentifier = expression as SimpleIdentifier;
      var element = simpleIdentifier.element;
      if (element is PromotableElementImpl &&
          !expression.typeOrThrow.isDartCoreNull &&
          typeSystem.isNullable(element.type) &&
          typeSystem.isNonNullable(staticType) &&
          flowAnalysis.isDefinitelyUnassigned(simpleIdentifier, element)) {
        diagnosticReporter.atNode(
          simpleIdentifier,
          WarningCode.CAST_FROM_NULLABLE_ALWAYS_FAILS,
          arguments: [simpleIdentifier.name],
        );
      }
    }
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitAssertInitializer(covariant AssertInitializerImpl node) {
    flowAnalysis.flow?.assert_begin();
    analyzeExpression(
      node.condition,
      SharedTypeSchemaView(typeProvider.boolType),
    );
    popRewrite();
    boolExpressionVerifier.checkForNonBoolExpression(
      node.condition,
      diagnosticCode: CompileTimeErrorCode.NON_BOOL_EXPRESSION,
      whyNotPromoted: flowAnalysis.flow?.whyNotPromoted(node.condition),
    );
    flowAnalysis.flow?.assert_afterCondition(node.condition);
    if (node.message case var message?) {
      analyzeExpression(message, operations.unknownType);
      popRewrite();
    }
    flowAnalysis.flow?.assert_end();
  }

  @override
  void visitAssertStatement(covariant AssertStatementImpl node) {
    inferenceLogWriter?.enterStatement(node);
    checkUnreachableNode(node);
    flowAnalysis.flow?.assert_begin();
    analyzeExpression(
      node.condition,
      SharedTypeSchemaView(typeProvider.boolType),
    );
    popRewrite();
    boolExpressionVerifier.checkForNonBoolExpression(
      node.condition,
      diagnosticCode: CompileTimeErrorCode.NON_BOOL_EXPRESSION,
      whyNotPromoted: flowAnalysis.flow?.whyNotPromoted(node.condition),
    );
    flowAnalysis.flow?.assert_afterCondition(node.condition);
    if (node.message case var message?) {
      analyzeExpression(message, operations.unknownType);
      popRewrite();
    }
    flowAnalysis.flow?.assert_end();
    inferenceLogWriter?.exitStatement(node);
  }

  @override
  void visitAssignmentExpression(
    AssignmentExpression node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    _assignmentExpressionResolver.resolve(
      node as AssignmentExpressionImpl,
      contextType: contextType,
    );
    _insertImplicitCallReference(
      insertGenericFunctionInstantiation(node, contextType: contextType),
      contextType: contextType,
    );
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitAugmentedExpression(
    covariant AugmentedExpressionImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    super.visitAugmentedExpression(node);
  }

  @override
  void visitAugmentedInvocation(
    covariant AugmentedInvocationImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    super.visitAugmentedInvocation(node);
  }

  @override
  void visitAwaitExpression(
    covariant AwaitExpressionImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    analyzeExpression(
      node.expression,
      SharedTypeSchemaView(_createFutureOr(contextType)),
    );
    popRewrite();
    typeAnalyzer.visitAwaitExpression(node);
    _insertImplicitCallReference(
      insertGenericFunctionInstantiation(node, contextType: contextType),
      contextType: contextType,
    );
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitBinaryExpression(
    BinaryExpression node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    _binaryExpressionResolver.resolve(
      node as BinaryExpressionImpl,
      contextType: contextType,
    );
    _insertImplicitCallReference(
      insertGenericFunctionInstantiation(node, contextType: contextType),
      contextType: contextType,
    );
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitBlock(Block node) {
    inferenceLogWriter?.enterStatement(node);
    checkUnreachableNode(node);
    node.visitChildren(this);
    inferenceLogWriter?.exitStatement(node);
  }

  @override
  TypeImpl visitBlockFunctionBody(
    covariant BlockFunctionBodyImpl node, {
    TypeImpl? imposedType,
  }) {
    var oldBodyContext = _bodyContext;
    try {
      _bodyContext = BodyInferenceContext(
        typeSystem: typeSystem,
        node: node,
        imposedType: imposedType,
      );
      checkUnreachableNode(node);
      node.visitChildren(this);
      return _finishFunctionBodyInference();
    } finally {
      _bodyContext = oldBodyContext;
    }
  }

  @override
  void visitBooleanLiteral(
    covariant BooleanLiteralImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    flowAnalysis.flow?.booleanLiteral(node, node.value);
    checkUnreachableNode(node);
    node.visitChildren(this);
    typeAnalyzer.visitBooleanLiteral(node);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitBreakStatement(BreakStatement node) {
    //
    // We do not visit the label because it needs to be visited in the context
    // of the statement.
    //
    checkUnreachableNode(node);
    flowAnalysis.breakStatement(node);
  }

  @override
  void visitCascadeExpression(
    covariant CascadeExpressionImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    analyzeExpression(node.target, SharedTypeSchemaView(contextType));
    var targetType = node.target.staticType ?? typeProvider.dynamicType;
    popRewrite();

    flowAnalysis.flow!.cascadeExpression_afterTarget(
      node.target,
      SharedTypeView(targetType),
      isNullAware: node.isNullAware,
    );

    if (node.isNullAware) {
      flowAnalysis.flow!.nullAwareAccess_rightBegin(
        node.target,
        SharedTypeView(targetType),
      );
      _unfinishedNullShorts.add(node.nullShortingTermination);
    }

    for (var cascadeSection in node.cascadeSections) {
      analyzeExpression(cascadeSection, operations.unknownType);
      popRewrite();
    }

    typeAnalyzer.visitCascadeExpression(node);

    nullShortingTermination(node);
    flowAnalysis.flow!.cascadeExpression_end(node);
    _insertImplicitCallReference(node, contextType: contextType);
    nullSafetyDeadCodeVerifier.verifyCascadeExpression(node);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitCatchClause(CatchClause node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
  }

  @override
  void visitCatchClauseParameter(CatchClauseParameter node) {
    node.visitChildren(this);
  }

  @override
  void visitClassDeclaration(covariant ClassDeclarationImpl node) {
    var declaredFragment = node.declaredFragment!;
    var declaredElement = declaredFragment.element;

    //
    // Continue the class resolution.
    //
    var outerType = enclosingClass;
    try {
      enclosingClass = declaredElement;
      checkUnreachableNode(node);
      node.visitChildren(this);
      elementResolver.visitClassDeclaration(node);
    } finally {
      enclosingClass = outerType;
    }

    baseOrFinalTypeVerifier.checkElement(
      declaredElement,
      node.implementsClause,
    );
  }

  @override
  void visitClassTypeAlias(covariant ClassTypeAliasImpl node) {
    var declaredFragment = node.declaredFragment!;
    var declaredElement = declaredFragment.element;

    checkUnreachableNode(node);
    node.visitChildren(this);
    elementResolver.visitClassTypeAlias(node);
    baseOrFinalTypeVerifier.checkElement(
      declaredElement,
      node.implementsClause,
    );
  }

  @override
  void visitComment(Comment node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
  }

  @override
  void visitCommentReference(CommentReference node) {
    //
    // We do not visit the expression because it needs to be visited in the
    // context of the reference.
    //
    elementResolver.visitCommentReference(node);
  }

  @override
  void visitCompilationUnit(CompilationUnit node) {
    conditionallyStartInferenceLogging(dump: inferenceLoggingPredicate(source));
    try {
      NodeList<Directive> directives = node.directives;
      int directiveCount = directives.length;
      for (int i = 0; i < directiveCount; i++) {
        directives[i].accept(this);
      }
      NodeList<CompilationUnitMember> declarations = node.declarations;
      int declarationCount = declarations.length;
      for (int i = 0; i < declarationCount; i++) {
        declarations[i].accept(this);
      }
      checkIdle();
    } finally {
      stopInferenceLogging();
    }
  }

  @override
  void visitConditionalExpression(
    covariant ConditionalExpressionImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    ExpressionImpl condition = node.condition;
    var flow = flowAnalysis.flow;
    flow?.conditional_conditionBegin();

    analyzeExpression(
      node.condition,
      SharedTypeSchemaView(typeProvider.boolType),
    );
    condition = popRewrite()!;
    var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(condition);
    boolExpressionVerifier.checkForNonBoolCondition(
      condition,
      whyNotPromoted: whyNotPromoted,
    );

    if (flow != null) {
      flow.conditional_thenBegin(condition, node);
      checkUnreachableNode(node.thenExpression);
    }
    analyzeExpression(node.thenExpression, SharedTypeSchemaView(contextType));
    popRewrite();
    nullSafetyDeadCodeVerifier.flowEnd(node.thenExpression);

    ExpressionImpl elseExpression = node.elseExpression;

    if (flow != null) {
      flow.conditional_elseBegin(
        node.thenExpression,
        SharedTypeView(node.thenExpression.typeOrThrow),
      );
      checkUnreachableNode(elseExpression);
      analyzeExpression(elseExpression, SharedTypeSchemaView(contextType));
    } else {
      analyzeExpression(elseExpression, SharedTypeSchemaView(contextType));
    }
    elseExpression = popRewrite()!;

    typeAnalyzer.visitConditionalExpression(node, contextType: contextType);
    if (flow != null) {
      flow.conditional_end(
        node,
        SharedTypeView(node.typeOrThrow),
        elseExpression,
        SharedTypeView(elseExpression.typeOrThrow),
      );
      nullSafetyDeadCodeVerifier.flowEnd(elseExpression);
    }
    _insertImplicitCallReference(node, contextType: contextType);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitConfiguration(Configuration node) {
    // Don't visit the children. For the time being we don't resolve anything
    // inside the configuration.
  }

  @override
  void visitConstructorDeclaration(covariant ConstructorDeclarationImpl node) {
    var fragment = node.declaredFragment!;
    var element = fragment.element;
    var returnType = element.type.returnType;
    var outerFunction = enclosingFunction;

    try {
      enclosingFunction = element;
      assert(_thisType == null);
      _setupThisType();
      checkUnreachableNode(node);
      node.documentationComment?.accept(this);
      node.metadata.accept(this);
      node.returnType.accept(this);
      node.parameters.accept(this);

      flowAnalysis.bodyOrInitializer_enter(node, node.parameters);
      flowAnalysis.executableDeclaration_enter(
        node,
        node.parameters,
        isClosure: false,
      );

      node.initializers.accept(this);
      node.redirectedConstructor?.accept(this);
      node.body.resolve(this, returnType is DynamicType ? null : returnType);
      elementResolver.visitConstructorDeclaration(node);

      if (node.factoryKeyword != null) {
        checkForBodyMayCompleteNormally(body: node.body, errorNode: node);
      }
      flowAnalysis.executableDeclaration_exit(node.body, false);
      flowAnalysis.bodyOrInitializer_exit();
      nullSafetyDeadCodeVerifier.flowEnd(node);
    } finally {
      enclosingFunction = outerFunction;
      _thisType = null;
    }
  }

  @override
  void visitConstructorFieldInitializer(
    covariant ConstructorFieldInitializerImpl node,
  ) {
    //
    // We visit the expression, but do not visit the field name because it needs
    // to be visited in the context of the constructor field initializer node.
    //
    var fieldName = node.fieldName;
    var fieldElement = enclosingClass!.getField(fieldName.name);
    fieldName.element = fieldElement;
    var fieldType = fieldElement?.type ?? UnknownInferredType.instance;
    var expression = node.expression;
    analyzeExpression(expression, SharedTypeSchemaView(fieldType));
    expression = popRewrite()!;
    var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(expression);
    if (fieldElement != null) {
      var enclosingConstructor = enclosingFunction as ConstructorElementImpl;
      checkForFieldInitializerNotAssignable(
        node,
        fieldElement,
        isConstConstructor: enclosingConstructor.isConst,
        whyNotPromoted: whyNotPromoted,
      );
    }
  }

  @override
  void visitConstructorName(ConstructorName node) {
    node.type.accept(this);
    elementResolver.visitConstructorName(node as ConstructorNameImpl);
  }

  @override
  void visitConstructorReference(
    covariant ConstructorReferenceImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    _constructorReferenceResolver.resolve(node, contextType: contextType);
    _insertImplicitCallReference(node, contextType: contextType);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitConstructorSelector(ConstructorSelector node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
  }

  @override
  void visitContinueStatement(ContinueStatement node) {
    //
    // We do not visit the label because it needs to be visited in the context
    // of the statement.
    //
    checkUnreachableNode(node);
    flowAnalysis.continueStatement(node);
  }

  @override
  void visitDeclaredIdentifier(DeclaredIdentifier node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
    elementResolver.visitDeclaredIdentifier(node);
  }

  @override
  void visitDefaultFormalParameter(covariant DefaultFormalParameterImpl node) {
    var fragment = node.declaredFragment!;
    checkUnreachableNode(node);
    node.parameter.accept(this);
    var defaultValue = node.defaultValue;
    if (defaultValue != null) {
      analyzeExpression(
        defaultValue,
        SharedTypeSchemaView(fragment.element.type),
      );
      popRewrite();
    }

    if (fragment is DefaultParameterFragmentImpl && node.isOfLocalFunction) {
      fragment.constantInitializer = defaultValue;
    }
  }

  @override
  void visitDoStatement(covariant DoStatementImpl node) {
    inferenceLogWriter?.enterStatement(node);
    checkUnreachableNode(node);

    var condition = node.condition;

    flowAnalysis.flow?.doStatement_bodyBegin(node);
    node.body.accept(this);

    flowAnalysis.flow?.doStatement_conditionBegin();
    analyzeExpression(condition, SharedTypeSchemaView(typeProvider.boolType));
    condition = popRewrite()!;
    var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(condition);
    boolExpressionVerifier.checkForNonBoolCondition(
      condition,
      whyNotPromoted: whyNotPromoted,
    );

    flowAnalysis.flow?.doStatement_end(condition);
    inferenceLogWriter?.exitStatement(node);
  }

  @override
  void visitDotShorthandConstructorInvocation(
    covariant DotShorthandConstructorInvocationImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);

    // If [isDotShorthand] is set, cache the context type for resolution.
    if (isDotShorthand(node)) {
      pushDotShorthandContext(node, SharedTypeSchemaView(contextType));
    }

    _instanceCreationExpressionResolver.resolveDotShorthand(
      node,
      contextType: contextType,
    );

    if (isDotShorthand(node)) {
      popDotShorthandContext();
    }

    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitDotShorthandInvocation(
    covariant DotShorthandInvocationImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);

    // If [isDotShorthand] is set, cache the context type for resolution.
    if (isDotShorthand(node)) {
      pushDotShorthandContext(node, SharedTypeSchemaView(contextType));
    }

    checkUnreachableNode(node);
    var whyNotPromotedArguments =
        <Map<SharedTypeView, NonPromotionReason> Function()>[];

    node.typeArguments?.accept(this);
    var rewrittenExpression = elementResolver.visitDotShorthandInvocation(
      node,
      whyNotPromotedArguments: whyNotPromotedArguments,
      contextType: contextType,
    );
    switch (rewrittenExpression) {
      case null:
        // In this case, we didn't rewrite anything. The [node] is a static
        // method invocation.
        break;
      case FunctionExpressionInvocationImpl():
        _resolveRewrittenFunctionExpressionInvocation(
          rewrittenExpression,
          whyNotPromotedArguments,
          contextType: contextType,
        );
      case DotShorthandConstructorInvocationImpl():
        _instanceCreationExpressionResolver.resolveDotShorthand(
          rewrittenExpression,
          contextType: contextType,
        );
    }

    if (rewrittenExpression is FunctionExpressionInvocationImpl ||
        rewrittenExpression == null) {
      var replacement = insertGenericFunctionInstantiation(
        node,
        contextType: contextType,
      );
      checkForArgumentTypesNotAssignableInList(
        node.argumentList,
        whyNotPromotedArguments,
      );
      _insertImplicitCallReference(replacement, contextType: contextType);
    }

    if (isDotShorthand(node)) {
      popDotShorthandContext();
    }

    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitDotShorthandPropertyAccess(
    covariant DotShorthandPropertyAccessImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);

    // If [isDotShorthand] is set, cache the context type for resolution.
    if (isDotShorthand(node)) {
      pushDotShorthandContext(node, SharedTypeSchemaView(contextType));
    }

    checkUnreachableNode(node);
    var result = _propertyElementResolver.resolveDotShorthand(
      node,
      contextType: contextType,
    );
    _resolvePropertyAccessRhs_common(
      result,
      node,
      node.propertyName,
      contextType,
    );

    if (isDotShorthand(node)) {
      popDotShorthandContext();
    }

    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitDoubleLiteral(
    DoubleLiteral node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    node.visitChildren(this);
    typeAnalyzer.visitDoubleLiteral(node as DoubleLiteralImpl);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  TypeImpl visitEmptyFunctionBody(
    EmptyFunctionBody node, {
    TypeImpl? imposedType,
  }) {
    checkUnreachableNode(node);
    node.visitChildren(this);
    return imposedType ?? typeProvider.dynamicType;
  }

  @override
  void visitEmptyStatement(EmptyStatement node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
  }

  @override
  void visitEnumConstantArguments(EnumConstantArguments node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
  }

  @override
  void visitEnumConstantDeclaration(
    covariant EnumConstantDeclarationImpl node,
  ) {
    node.documentationComment?.accept(this);
    node.metadata.accept(this);
    checkUnreachableNode(node);

    var fragment = node.declaredFragment!;
    var initializer = fragment.constantInitializer;
    if (initializer is InstanceCreationExpressionImpl) {
      var constructorName = initializer.constructorName;
      var constructorElement = constructorName.element;
      if (constructorElement != null) {
        node.constructorElement2 = constructorElement;
        if (constructorElement.isFactory) {
          var constructorName = node.arguments?.constructorSelector?.name;
          var errorTarget = constructorName ?? node.name;
          diagnosticReporter.atEntity(
            errorTarget,
            CompileTimeErrorCode.ENUM_CONSTANT_INVOKES_FACTORY_CONSTRUCTOR,
          );
        }
      } else {
        if (constructorName.type.element2 is EnumElementImpl) {
          var nameNode = node.arguments?.constructorSelector?.name;
          if (nameNode != null) {
            diagnosticReporter.atNode(
              nameNode,
              CompileTimeErrorCode.UNDEFINED_ENUM_CONSTRUCTOR_NAMED,
              arguments: [nameNode.name],
            );
          } else {
            diagnosticReporter.atToken(
              node.name,
              CompileTimeErrorCode.UNDEFINED_ENUM_CONSTRUCTOR_UNNAMED,
            );
          }
        }
      }
      if (constructorElement != null) {
        var arguments = node.arguments;
        if (arguments != null) {
          var argumentList = arguments.argumentList;
          argumentList.correspondingStaticParameters2 =
              ResolverVisitor.resolveArgumentsToParameters(
                argumentList: argumentList,
                formalParameters: constructorElement.formalParameters,
                diagnosticReporter: diagnosticReporter,
              );
        } else if (definingLibrary.featureSet.isEnabled(
          Feature.enhanced_enums,
        )) {
          var requiredParameterCount =
              constructorElement.formalParameters
                  .where((e) => e.isRequiredPositional)
                  .length;
          if (requiredParameterCount != 0) {
            _reportNotEnoughPositionalArguments(
              token: node.name,
              requiredParameterCount: requiredParameterCount,
              actualArgumentCount: 0,
              nameNode: node,
              diagnosticReporter: diagnosticReporter,
            );
          }
        }
      }
    }

    var arguments = node.arguments;
    if (arguments != null) {
      var argumentList = arguments.argumentList;
      for (var argument in argumentList.arguments) {
        analyzeExpression(
          argument,
          SharedTypeSchemaView(
            argument.correspondingParameter?.type ??
                UnknownInferredType.instance,
          ),
        );
        popRewrite();
      }
      arguments.typeArguments?.accept(this);

      var whyNotPromotedArguments =
          <Map<SharedTypeView, NonPromotionReason> Function()>[];
      checkForArgumentTypesNotAssignableInList(
        argumentList,
        whyNotPromotedArguments,
      );
    }

    elementResolver.visitEnumConstantDeclaration(node);
  }

  @override
  void visitEnumDeclaration(covariant EnumDeclarationImpl node) {
    //
    // Continue the enum resolution.
    //
    var outerType = enclosingClass;
    try {
      enclosingClass = node.declaredFragment!.element;
      checkUnreachableNode(node);
      node.visitChildren(this);
      elementResolver.visitEnumDeclaration(node);
    } finally {
      enclosingClass = outerType;
    }
  }

  @override
  void visitExportDirective(covariant ExportDirectiveImpl node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
    elementResolver.visitExportDirective(node);
  }

  @override
  TypeImpl visitExpressionFunctionBody(
    covariant ExpressionFunctionBodyImpl node, {
    TypeImpl? imposedType,
  }) {
    var oldBodyContext = _bodyContext;
    try {
      var bodyContext =
          _bodyContext = BodyInferenceContext(
            typeSystem: typeSystem,
            node: node,
            imposedType: imposedType,
          );

      checkUnreachableNode(node);
      analyzeExpression(
        node.expression,
        SharedTypeSchemaView(
          bodyContext.contextType ?? UnknownInferredType.instance,
        ),
      );
      popRewrite();

      flowAnalysis.flow?.handleExit();

      bodyContext.addReturnExpression(node.expression);
      return _finishFunctionBodyInference();
    } finally {
      _bodyContext = oldBodyContext;
    }
  }

  @override
  void visitExpressionStatement(covariant ExpressionStatementImpl node) {
    inferenceLogWriter?.enterStatement(node);
    checkUnreachableNode(node);
    analyzeExpression(node.expression, operations.unknownType);
    popRewrite();
    inferenceLogWriter?.exitStatement(node);
  }

  @override
  void visitExtendsClause(ExtendsClause node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
  }

  @override
  void visitExtensionDeclaration(covariant ExtensionDeclarationImpl node) {
    var outerExtension = enclosingExtension;
    try {
      enclosingExtension = node.declaredFragment!.element;
      checkUnreachableNode(node);
      node.visitChildren(this);
      elementResolver.visitExtensionDeclaration(node);
    } finally {
      enclosingExtension = outerExtension;
    }
  }

  @override
  void visitExtensionOnClause(ExtensionOnClause node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
  }

  @override
  void visitExtensionOverride(
    covariant ExtensionOverrideImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExtensionOverride(node, contextType);
    var whyNotPromotedArguments =
        <Map<SharedTypeView, NonPromotionReason> Function()>[];
    node.typeArguments?.accept(this);

    var receiverContextType = ExtensionMemberResolver(
      this,
    ).computeOverrideReceiverContextType(node);
    InvocationInferrer<ExtensionOverrideImpl>(
      resolver: this,
      node: node,
      argumentList: node.argumentList,
      contextType: UnknownInferredType.instance,
      whyNotPromotedArguments: whyNotPromotedArguments,
    ).resolveInvocation(
      rawType:
          receiverContextType == null
              ? null
              : FunctionTypeImpl.v2(
                typeParameters: const [],
                formalParameters: [
                  FormalParameterElementImpl.synthetic(
                    null,
                    receiverContextType,
                    ParameterKind.REQUIRED,
                  ),
                ],
                returnType: DynamicTypeImpl.instance,
                nullabilitySuffix: NullabilitySuffix.none,
              ),
    );

    extensionResolver.resolveOverride(node, whyNotPromotedArguments);
    inferenceLogWriter?.exitExtensionOverride(node);
  }

  @override
  void visitExtensionTypeDeclaration(
    covariant ExtensionTypeDeclarationImpl node,
  ) {
    var outerType = enclosingClass;
    try {
      enclosingClass = node.declaredFragment!.element;
      checkUnreachableNode(node);
      node.visitChildren(this);
      elementResolver.visitExtensionTypeDeclaration(node);
    } finally {
      enclosingClass = outerType;
    }
  }

  @override
  void visitFieldDeclaration(FieldDeclaration node) {
    try {
      assert(_thisType == null);
      _setupThisType();
      checkUnreachableNode(node);
      node.visitChildren(this);
      elementResolver.visitFieldDeclaration(node);
    } finally {
      _thisType = null;
    }
  }

  @override
  void visitFieldFormalParameter(FieldFormalParameter node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
    elementResolver.visitFieldFormalParameter(node);
  }

  @override
  void visitForElement(
    covariant ForElementImpl node, {
    CollectionLiteralContext? context,
  }) {
    inferenceLogWriter?.enterElement(node);
    _forResolver.resolveElement(node, context);
    inferenceLogWriter?.exitElement(node);
  }

  @override
  void visitFormalParameterList(covariant FormalParameterListImpl node) {
    // Formal parameter lists can contain default values, which in turn contain
    // expressions, so we need flow analysis to be available to process those
    // expressions.
    var isTopLevel = flowAnalysis.flow == null;
    if (isTopLevel) {
      flowAnalysis.bodyOrInitializer_enter(node, null);
    }
    checkUnreachableNode(node);
    node.visitChildren(this);
    if (isTopLevel) {
      flowAnalysis.bodyOrInitializer_exit();
    }
  }

  @override
  void visitForStatement(ForStatement node) {
    inferenceLogWriter?.enterStatement(node);
    checkUnreachableNode(node);
    _forResolver.resolveStatement(node as ForStatementImpl);
    nullSafetyDeadCodeVerifier.flowEnd(node.body);
    inferenceLogWriter?.exitStatement(node);
  }

  @override
  void visitFunctionDeclaration(covariant FunctionDeclarationImpl node) {
    bool isLocal = node.parent is FunctionDeclarationStatement;
    var fragment = node.declaredFragment!;
    var element = fragment.element;
    var functionType = element.type;
    var outerFunction = enclosingFunction;

    try {
      enclosingFunction = element;
      checkUnreachableNode(node);
      node.documentationComment?.accept(this);
      node.metadata.accept(this);
      node.returnType?.accept(this);

      if (isLocal) {
        flowAnalysis.flow!.functionExpression_begin(node);
      } else {
        flowAnalysis.bodyOrInitializer_enter(
          node,
          node.functionExpression.parameters,
        );
      }
      flowAnalysis.executableDeclaration_enter(
        node,
        node.functionExpression.parameters,
        isClosure: isLocal,
      );

      analyzeExpression(
        node.functionExpression,
        SharedTypeSchemaView(functionType),
      );
      popRewrite();
      elementResolver.visitFunctionDeclaration(node);

      if (!node.isSetter) {
        checkForBodyMayCompleteNormally(
          body: node.functionExpression.body,
          errorNode: node.name,
        );
      }
      flowAnalysis.executableDeclaration_exit(
        node.functionExpression.body,
        isLocal,
      );
      if (isLocal) {
        flowAnalysis.flow!.functionExpression_end();
      } else {
        flowAnalysis.bodyOrInitializer_exit();
      }
      nullSafetyDeadCodeVerifier.flowEnd(node);
    } finally {
      enclosingFunction = outerFunction;
    }
  }

  @override
  void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
    inferenceLogWriter?.enterStatement(node);
    checkUnreachableNode(node);
    node.visitChildren(this);
    inferenceLogWriter?.exitStatement(node);
  }

  @override
  void visitFunctionExpression(
    covariant FunctionExpressionImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    var outerFunction = enclosingFunction;
    enclosingFunction = node.declaredFragment!.element;

    _functionExpressionResolver.resolve(node, contextType: contextType);
    insertGenericFunctionInstantiation(node, contextType: contextType);

    enclosingFunction = outerFunction;
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitFunctionExpressionInvocation(
    covariant FunctionExpressionInvocationImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    analyzeExpression(
      node.function,
      SharedTypeSchemaView(UnknownInferredType.instance),
    );
    node.function = popRewrite()!;

    var whyNotPromotedArguments =
        <Map<SharedTypeView, NonPromotionReason> Function()>[];
    _functionExpressionInvocationResolver.resolve(
      node,
      whyNotPromotedArguments,
      contextType: contextType,
    );
    nullShortingTermination(node);
    var replacement = insertGenericFunctionInstantiation(
      node,
      contextType: contextType,
    );
    checkForArgumentTypesNotAssignableInList(
      node.argumentList,
      whyNotPromotedArguments,
    );
    _insertImplicitCallReference(replacement, contextType: contextType);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitFunctionReference(
    covariant FunctionReferenceImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);

    // If [isDotShorthand] is set, cache the context type for resolution.
    if (isDotShorthand(node)) {
      pushDotShorthandContext(node, SharedTypeSchemaView(contextType));
    }

    _functionReferenceResolver.resolve(node);

    if (isDotShorthand(node)) {
      popDotShorthandContext();
    }

    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitFunctionTypeAlias(FunctionTypeAlias node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
    elementResolver.visitFunctionTypeAlias(node);
  }

  @override
  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
    elementResolver.visitFunctionTypedFormalParameter(node);
  }

  @override
  void visitGenericFunctionType(GenericFunctionType node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
  }

  @override
  void visitGenericTypeAlias(GenericTypeAlias node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
    elementResolver.visitGenericTypeAlias(node);
  }

  @override
  void visitHideCombinator(HideCombinator node) {}

  @override
  void visitIfElement(
    covariant IfElementImpl node, {
    CollectionLiteralContext? context,
  }) {
    inferenceLogWriter?.enterElement(node);
    var caseClause = node.caseClause;
    if (caseClause != null) {
      var guardedPattern = caseClause.guardedPattern;
      analyzeIfCaseElement(
        node: node,
        expression: node.expression,
        pattern: guardedPattern.pattern,
        variables: guardedPattern.variables,
        guard: guardedPattern.whenClause?.expression,
        ifTrue: node.thenElement,
        ifFalse: node.elseElement,
        context: context,
      );
      // Stack: (Expression, Guard)
      popRewrite(); // guard
      popRewrite()!; // expression
    } else {
      analyzeIfElement(
        node: node,
        condition: node.expression,
        ifTrue: node.thenElement,
        ifFalse: node.elseElement,
        context: context,
      );
    }
    inferenceLogWriter?.exitElement(node);
  }

  @override
  void visitIfStatement(covariant IfStatementImpl node) {
    inferenceLogWriter?.enterStatement(node);
    checkUnreachableNode(node);

    var caseClause = node.caseClause;
    if (caseClause != null) {
      var guardedPattern = caseClause.guardedPattern;
      analyzeIfCaseStatement(
        node,
        node.expression,
        guardedPattern.pattern,
        guardedPattern.whenClause?.expression,
        node.thenStatement,
        node.elseStatement,
        guardedPattern.variables,
      );
      // Stack: (Expression, Guard)
      popRewrite(); // guard
      popRewrite()!; // expression
    } else {
      analyzeIfStatement(
        node,
        node.expression,
        node.thenStatement,
        node.elseStatement,
      );
    }
    inferenceLogWriter?.exitStatement(node);
  }

  @override
  void visitImplementsClause(ImplementsClause node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
  }

  @override
  void visitImplicitCallReference(
    covariant ImplicitCallReferenceImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    checkUnreachableNode(node);
    analyzeExpression(
      node.expression,
      SharedTypeSchemaView(UnknownInferredType.instance),
    );
    popRewrite();
    node.typeArguments?.accept(this);
  }

  @override
  void visitImportDirective(ImportDirective node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
    elementResolver.visitImportDirective(node as ImportDirectiveImpl);
  }

  @override
  void visitIndexExpression(
    covariant IndexExpressionImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);

    // If [isDotShorthand] is set, cache the context type for resolution.
    if (isDotShorthand(node)) {
      pushDotShorthandContext(node, SharedTypeSchemaView(contextType));
    }

    checkUnreachableNode(node);

    var target = node.target;
    if (target != null) {
      analyzeExpression(
        target,
        SharedTypeSchemaView(UnknownInferredType.instance),
      );
      popRewrite();
    }
    var targetType = node.realTarget.staticType;

    if (node.isNullAware) {
      _startNullAwareAccess(node, node.target);
      nullSafetyDeadCodeVerifier.visitNode(node.index);
    }

    var result = _propertyElementResolver.resolveIndexExpression(
      node: node,
      hasRead: true,
      hasWrite: false,
    );

    var element = result.readElement2;
    node.element = element as MethodElement?;

    analyzeExpression(
      node.index,
      SharedTypeSchemaView(result.indexContextType),
    );
    popRewrite();
    var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(node.index);
    checkIndexExpressionIndex(
      node.index,
      readElement: result.readElement2 as ExecutableElement2OrMember?,
      writeElement: null,
      whyNotPromoted: whyNotPromoted,
    );

    DartType type;
    if (identical(targetType, NeverTypeImpl.instance)) {
      type = NeverTypeImpl.instance;
    } else if (element is MethodElement) {
      type = element.returnType;
    } else if (targetType is DynamicType) {
      type = DynamicTypeImpl.instance;
    } else {
      type = InvalidTypeImpl.instance;
    }
    node.recordStaticType(type, resolver: this);
    var replacement = insertGenericFunctionInstantiation(
      node,
      contextType: contextType,
    );

    nullShortingTermination(node, rewrittenExpression: replacement);
    _insertImplicitCallReference(replacement, contextType: contextType);
    nullSafetyDeadCodeVerifier.verifyIndexExpression(node);

    if (isDotShorthand(node)) {
      popDotShorthandContext();
    }

    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitInstanceCreationExpression(
    covariant InstanceCreationExpressionImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    _instanceCreationExpressionResolver.resolve(node, contextType: contextType);
    _insertImplicitCallReference(node, contextType: contextType);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitIntegerLiteral(
    IntegerLiteral node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    node.visitChildren(this);
    typeAnalyzer.visitIntegerLiteral(
      node as IntegerLiteralImpl,
      contextType: contextType,
    );
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitInterpolationExpression(
    covariant InterpolationExpressionImpl node,
  ) {
    checkUnreachableNode(node);
    analyzeExpression(node.expression, operations.unknownType);
    popRewrite();
  }

  @override
  void visitInterpolationString(InterpolationString node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
  }

  @override
  void visitIsExpression(
    covariant IsExpressionImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);

    analyzeExpression(
      node.expression,
      SharedTypeSchemaView(UnknownInferredType.instance),
    );
    popRewrite();

    checkUnreachableNode(node.type);
    node.type.accept(this);

    typeAnalyzer.visitIsExpression(node);
    flowAnalysis.isExpression(node);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitLabel(Label node) {}

  @override
  void visitLabeledStatement(covariant LabeledStatementImpl node) {
    inferenceLogWriter?.enterStatement(node);
    flowAnalysis.labeledStatement_enter(node);
    checkUnreachableNode(node);
    node.visitChildren(this);
    flowAnalysis.labeledStatement_exit(node);
    inferenceLogWriter?.exitStatement(node);
  }

  @override
  void visitLibraryDirective(LibraryDirective node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
    elementResolver.visitLibraryDirective(node);
  }

  @override
  void visitLibraryIdentifier(
    LibraryIdentifier node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {}

  @override
  void visitListLiteral(
    covariant ListLiteralImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    _typedLiteralResolver.resolveListLiteral(node, contextType: contextType);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitMapLiteralEntry(
    covariant MapLiteralEntryImpl node, {
    CollectionLiteralContext? context,
  }) {
    inferenceLogWriter?.enterElement(node);
    checkUnreachableNode(node);

    // If the key is null-aware, the context of the expression under `?` should
    // be changed to the nullable version of the downwards context.
    var keyTypeContext = context?.keyType;
    if (keyTypeContext != null && node.keyQuestion != null) {
      keyTypeContext = typeSystem.makeNullable(keyTypeContext);
    }
    var keyType = analyzeExpression(
      node.key,
      SharedTypeSchemaView(keyTypeContext ?? UnknownInferredType.instance),
    );
    popRewrite();

    flowAnalysis.flow?.nullAwareMapEntry_valueBegin(
      node.key,
      keyType,
      isKeyNullAware: node.keyQuestion != null,
    );

    // If the value is null-aware, the context of the expression under `?`
    // should be changed to the nullable version of the downwards context.
    var valueTypeContext = context?.valueType;
    if (valueTypeContext != null && node.valueQuestion != null) {
      valueTypeContext = typeSystem.makeNullable(valueTypeContext);
    }
    analyzeExpression(
      node.value,
      SharedTypeSchemaView(valueTypeContext ?? UnknownInferredType.instance),
    );
    popRewrite();

    flowAnalysis.flow?.nullAwareMapEntry_end(
      isKeyNullAware: node.keyQuestion != null,
    );
    inferenceLogWriter?.exitElement(node);
  }

  @override
  void visitMethodDeclaration(covariant MethodDeclarationImpl node) {
    var fragment = node.declaredFragment!;
    var element = fragment.element;
    var returnType = element.returnType;
    var outerFunction = enclosingFunction;

    try {
      enclosingFunction = element;
      assert(_thisType == null);
      _setupThisType();
      checkUnreachableNode(node);
      node.documentationComment?.accept(this);
      node.metadata.accept(this);
      node.returnType?.accept(this);
      node.typeParameters?.accept(this);
      node.parameters?.accept(this);

      flowAnalysis.bodyOrInitializer_enter(node, node.parameters);
      flowAnalysis.executableDeclaration_enter(
        node,
        node.parameters,
        isClosure: false,
      );

      node.body.resolve(this, returnType is DynamicType ? null : returnType);
      elementResolver.visitMethodDeclaration(node);

      if (!node.isSetter) {
        checkForBodyMayCompleteNormally(body: node.body, errorNode: node.name);
      }
      flowAnalysis.executableDeclaration_exit(node.body, false);
      flowAnalysis.bodyOrInitializer_exit();
      nullSafetyDeadCodeVerifier.flowEnd(node);
    } finally {
      enclosingFunction = outerFunction;
      _thisType = null;
    }
  }

  @override
  void visitMethodInvocation(
    covariant MethodInvocationImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);

    // If [isDotShorthand] is set, cache the context type for resolution.
    if (isDotShorthand(node)) {
      pushDotShorthandContext(node, SharedTypeSchemaView(contextType));
    }

    checkUnreachableNode(node);
    var whyNotPromotedArguments =
        <Map<SharedTypeView, NonPromotionReason> Function()>[];
    var target = node.target;
    if (target != null) {
      analyzeExpression(target, operations.unknownType);
      target = popRewrite();
    }

    if (node.isNullAware) {
      _startNullAwareAccess(node, target);
      nullSafetyDeadCodeVerifier.visitNode(node.methodName);
    }

    node.typeArguments?.accept(this);
    var functionRewrite = elementResolver.visitMethodInvocation(
      node,
      whyNotPromotedArguments: whyNotPromotedArguments,
      contextType: contextType,
    );

    if (functionRewrite != null) {
      _resolveRewrittenFunctionExpressionInvocation(
        functionRewrite,
        whyNotPromotedArguments,
        contextType: contextType,
      );
    }
    nullShortingTermination(node, rewrittenExpression: functionRewrite);
    var replacement = insertGenericFunctionInstantiation(
      node,
      contextType: contextType,
    );
    checkForArgumentTypesNotAssignableInList(
      node.argumentList,
      whyNotPromotedArguments,
    );
    _insertImplicitCallReference(replacement, contextType: contextType);
    nullSafetyDeadCodeVerifier.verifyMethodInvocation(node);

    if (isDotShorthand(node)) {
      popDotShorthandContext();
    }

    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitMixinDeclaration(covariant MixinDeclarationImpl node) {
    var declaredFragment = node.declaredFragment!;
    var declaredElement = declaredFragment.element;

    //
    // Continue the class resolution.
    //
    var outerType = enclosingClass;
    try {
      enclosingClass = node.declaredFragment!.element;
      checkUnreachableNode(node);
      node.visitChildren(this);
      elementResolver.visitMixinDeclaration(node);
    } finally {
      enclosingClass = outerType;
    }

    baseOrFinalTypeVerifier.checkElement(
      declaredElement,
      node.implementsClause,
    );
  }

  @override
  void visitMixinOnClause(MixinOnClause node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
  }

  @override
  void visitNamedExpression(
    covariant NamedExpressionImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    node.name.accept(this);
    analyzeExpression(node.expression, SharedTypeSchemaView(contextType));
    popRewrite();
    typeAnalyzer.visitNamedExpression(node);
    // Any "why not promoted" information that flow analysis had associated with
    // `node.expression` now needs to be forwarded to `node`, so that when
    // `visitArgumentList` iterates through the arguments, it will find it.
    flowAnalysis.flow?.forwardExpression(node, node.expression);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitNamedType(NamedType node) {
    // All TypeName(s) are already resolved, so we don't resolve it here.
    // But there might be type arguments with Expression(s), such as default
    // values for formal parameters of GenericFunctionType(s). These are
    // invalid, but if they exist, they should be resolved.
    node.typeArguments?.accept(this);
  }

  @override
  void visitNativeClause(NativeClause node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
  }

  @override
  TypeImpl visitNativeFunctionBody(
    covariant NativeFunctionBodyImpl node, {
    TypeImpl? imposedType,
  }) {
    checkUnreachableNode(node);
    if (node.stringLiteral case var stringLiteral?) {
      analyzeExpression(stringLiteral, operations.unknownType);
      popRewrite();
    }
    return imposedType ?? typeProvider.dynamicType;
  }

  @override
  void visitNullAwareElement(
    covariant NullAwareElementImpl node, {
    CollectionLiteralContext? context,
  }) {
    inferenceLogWriter?.enterElement(node);

    var elementType = context?.elementType;
    if (elementType != null) {
      elementType = typeSystem.makeNullable(elementType);
    }

    analyzeExpression(
      node.value,
      SharedTypeSchemaView(elementType ?? UnknownInferredType.instance),
    );
    popRewrite();

    inferenceLogWriter?.exitElement(node);
  }

  @override
  void visitNullLiteral(
    NullLiteral node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    node.visitChildren(this);
    typeAnalyzer.visitNullLiteral(node as NullLiteralImpl);
    flowAnalysis.flow?.nullLiteral(node, SharedTypeView(node.typeOrThrow));
    checkUnreachableNode(node);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitParenthesizedExpression(
    covariant ParenthesizedExpressionImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    analyzeExpression(node.expression, SharedTypeSchemaView(contextType));
    popRewrite();
    typeAnalyzer.visitParenthesizedExpression(node);
    flowAnalysis.flow?.parenthesizedExpression(node, node.expression);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitPartDirective(PartDirective node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
    elementResolver.visitPartDirective(node);
  }

  @override
  void visitPartOfDirective(PartOfDirective node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
    elementResolver.visitPartOfDirective(node);
  }

  @override
  void visitPatternAssignment(
    covariant PatternAssignmentImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    var analysisResult = analyzePatternAssignment(
      node,
      node.pattern,
      node.expression,
    );
    node.patternTypeSchema =
        analysisResult.patternSchema.unwrapTypeSchemaView();
    node.recordStaticType(
      // TODO(paulberry): make this type argument unnecessary by changing the
      // parameter of `ExpressionImpl.recordStaticType` to `TypeImpl`.
      analysisResult.type.unwrapTypeView<TypeImpl>(),
      resolver: this,
    );
    popRewrite(); // expression
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitPatternVariableDeclaration(
    covariant PatternVariableDeclarationImpl node,
  ) {
    var patternSchema =
        analyzePatternVariableDeclaration(
          node,
          node.pattern,
          node.expression,
          isFinal: node.keyword.keyword == Keyword.FINAL,
        ).patternSchema;
    node.patternTypeSchema = patternSchema.unwrapTypeSchemaView();
    popRewrite(); // expression
  }

  @override
  void visitPatternVariableDeclarationStatement(
    PatternVariableDeclarationStatement node,
  ) {
    inferenceLogWriter?.enterStatement(node);
    checkUnreachableNode(node);
    node.declaration.accept(this);
    inferenceLogWriter?.exitStatement(node);
  }

  @override
  void visitPostfixExpression(
    covariant PostfixExpressionImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);

    // If [isDotShorthand] is set, cache the context type for resolution.
    if (isDotShorthand(node)) {
      pushDotShorthandContext(node, SharedTypeSchemaView(contextType));
    }

    checkUnreachableNode(node);
    _postfixExpressionResolver.resolve(node, contextType: contextType);
    _insertImplicitCallReference(
      insertGenericFunctionInstantiation(node, contextType: contextType),
      contextType: contextType,
    );

    if (isDotShorthand(node)) {
      popDotShorthandContext();
    }

    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitPrefixedIdentifier(
    covariant PrefixedIdentifierImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    var rewrittenPropertyAccess = _prefixedIdentifierResolver.resolve(
      node,
      contextType: contextType,
    );
    if (rewrittenPropertyAccess != null) {
      _resolvePropertyAccessRhs(rewrittenPropertyAccess, contextType);
      // We did record that `node` was replaced with `rewrittenPropertyAccess`.
      // But if `rewrittenPropertyAccess` was itself rewritten, replace the
      // rewrite result of `node`.
      assert(() {
        var rewrite = _replacements[rewrittenPropertyAccess];
        if (rewrite != null) {
          _replacements[node] = rewrite;
        }
        return true;
      }());
      inferenceLogWriter?.exitExpression(node);
      return;
    }
    _insertImplicitCallReference(
      insertGenericFunctionInstantiation(node, contextType: contextType),
      contextType: contextType,
    );
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitPrefixExpression(
    PrefixExpression node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    _prefixExpressionResolver.resolve(
      node as PrefixExpressionImpl,
      contextType: contextType,
    );
    _insertImplicitCallReference(
      insertGenericFunctionInstantiation(node, contextType: contextType),
      contextType: contextType,
    );
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitPropertyAccess(
    covariant PropertyAccessImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);

    // If [isDotShorthand] is set, cache the context type for resolution.
    if (isDotShorthand(node)) {
      pushDotShorthandContext(node, SharedTypeSchemaView(contextType));
    }

    checkUnreachableNode(node);

    var target = node.target;
    if (target != null) {
      analyzeExpression(
        target,
        SharedTypeSchemaView(UnknownInferredType.instance),
      );
      popRewrite();
    }

    checkUnreachableNode(node.propertyName);
    _resolvePropertyAccessRhs(node, contextType);

    if (isDotShorthand(node)) {
      popDotShorthandContext();
    }

    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitRecordLiteral(
    covariant RecordLiteralImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    _recordLiteralResolver.resolve(node, contextType: contextType);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitRecordTypeAnnotation(covariant RecordTypeAnnotationImpl node) {
    // All RecordTypeAnnotation(s) are already resolved, so we don't resolve
    // it here. But there might be types with Expression(s), such as default
    // values for formal parameters of GenericFunctionType(s). These are
    // invalid, but if they exist, they should be resolved.
    node.visitChildren(this);
  }

  @override
  void visitRecordTypeAnnotationNamedField(
    RecordTypeAnnotationNamedField node,
  ) {
    node.visitChildren(this);
    elementResolver.visitRecordTypeAnnotationNamedField(node);
  }

  @override
  void visitRecordTypeAnnotationNamedFields(
    RecordTypeAnnotationNamedFields node,
  ) {
    node.visitChildren(this);
  }

  @override
  void visitRecordTypeAnnotationPositionalField(
    RecordTypeAnnotationPositionalField node,
  ) {
    node.visitChildren(this);
    elementResolver.visitRecordTypeAnnotationPositionalField(node);
  }

  @override
  void visitRedirectingConstructorInvocation(
    RedirectingConstructorInvocation node,
  ) {
    //
    // We visit the argument list, but do not visit the optional identifier
    // because it needs to be visited in the context of the constructor
    // invocation.
    //
    var whyNotPromotedArguments =
        <Map<SharedTypeView, NonPromotionReason> Function()>[];
    elementResolver.visitRedirectingConstructorInvocation(
      node as RedirectingConstructorInvocationImpl,
    );
    InvocationInferrer<RedirectingConstructorInvocationImpl>(
      resolver: this,
      node: node,
      argumentList: node.argumentList,
      contextType: UnknownInferredType.instance,
      whyNotPromotedArguments: whyNotPromotedArguments,
    ).resolveInvocation(rawType: node.element?.type);
    checkForArgumentTypesNotAssignableInList(
      node.argumentList,
      whyNotPromotedArguments,
    );
  }

  @override
  void visitRepresentationConstructorName(RepresentationConstructorName node) {}

  @override
  void visitRepresentationDeclaration(RepresentationDeclaration node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
    elementResolver.visitRepresentationDeclaration(node);
  }

  @override
  void visitRethrowExpression(
    RethrowExpression node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    node.visitChildren(this);
    typeAnalyzer.visitRethrowExpression(node as RethrowExpressionImpl);
    flowAnalysis.flow?.handleExit();
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitReturnStatement(covariant ReturnStatementImpl node) {
    inferenceLogWriter?.enterStatement(node);
    checkUnreachableNode(node);
    var expression = node.expression;
    if (expression != null) {
      analyzeExpression(
        expression,
        SharedTypeSchemaView(
          bodyContext?.contextType ?? UnknownInferredType.instance,
        ),
      );
      // Pick up the expression again in case it was rewritten.
      expression = popRewrite();
    }

    bodyContext?.addReturnExpression(expression);
    flowAnalysis.flow?.handleExit();
    inferenceLogWriter?.exitStatement(node);
  }

  @override
  void visitSetOrMapLiteral(
    SetOrMapLiteral node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    _typedLiteralResolver.resolveSetOrMapLiteral(
      node,
      contextType: contextType,
    );
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitShowCombinator(ShowCombinator node) {}

  @override
  void visitSimpleFormalParameter(SimpleFormalParameter node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
    elementResolver.visitSimpleFormalParameter(node);
  }

  @override
  void visitSimpleIdentifier(
    covariant SimpleIdentifierImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    _simpleIdentifierResolver.resolve(node, contextType: contextType);
    _insertImplicitCallReference(
      insertGenericFunctionInstantiation(node, contextType: contextType),
      contextType: contextType,
    );
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitSimpleStringLiteral(
    SimpleStringLiteral node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    node.visitChildren(this);
    typeAnalyzer.visitSimpleStringLiteral(node as SimpleStringLiteralImpl);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitSpreadElement(
    covariant SpreadElementImpl node, {
    CollectionLiteralContext? context,
  }) {
    inferenceLogWriter?.enterElement(node);
    var iterableType = context?.iterableType;
    if (iterableType != null && node.isNullAware) {
      iterableType = typeSystem.makeNullable(iterableType);
    }
    checkUnreachableNode(node);
    analyzeExpression(
      node.expression,
      SharedTypeSchemaView(iterableType ?? UnknownInferredType.instance),
    );
    popRewrite();

    if (!node.isNullAware) {
      nullableDereferenceVerifier.expression(
        CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_IN_SPREAD,
        node.expression,
      );
    }

    inferenceLogWriter?.exitElement(node);
  }

  @override
  void visitStringInterpolation(
    StringInterpolation node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    node.visitChildren(this);
    typeAnalyzer.visitStringInterpolation(node as StringInterpolationImpl);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
    //
    // We visit the argument list, but do not visit the optional identifier
    // because it needs to be visited in the context of the constructor
    // invocation.
    //
    var whyNotPromotedArguments =
        <Map<SharedTypeView, NonPromotionReason> Function()>[];
    elementResolver.visitSuperConstructorInvocation(
      node as SuperConstructorInvocationImpl,
    );
    InvocationInferrer<SuperConstructorInvocationImpl>(
      resolver: this,
      node: node,
      argumentList: node.argumentList,
      contextType: UnknownInferredType.instance,
      whyNotPromotedArguments: whyNotPromotedArguments,
    ).resolveInvocation(rawType: node.element?.type);
    checkForArgumentTypesNotAssignableInList(
      node.argumentList,
      whyNotPromotedArguments,
    );
  }

  @override
  void visitSuperExpression(
    SuperExpression node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    node.visitChildren(this);
    elementResolver.visitSuperExpression(node);
    typeAnalyzer.visitSuperExpression(node as SuperExpressionImpl);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitSuperFormalParameter(SuperFormalParameter node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
  }

  @override
  void visitSwitchExpression(
    covariant SwitchExpressionImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    var previousExhaustiveness = legacySwitchExhaustiveness;
    var staticType =
        analyzeSwitchExpression(
          node,
          node.expression,
          node.cases.length,
          SharedTypeSchemaView(contextType),
        ).type.unwrapTypeView<TypeImpl>();
    node.recordStaticType(staticType, resolver: this);
    popRewrite();
    legacySwitchExhaustiveness = previousExhaustiveness;
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitSwitchStatement(covariant SwitchStatementImpl node) {
    inferenceLogWriter?.enterStatement(node);
    // Stack: ()
    checkUnreachableNode(node);

    var previousExhaustiveness = legacySwitchExhaustiveness;
    analyzeSwitchStatement(node, node.expression, node.memberGroups.length);
    // Stack: (Expression)
    popRewrite();
    // Stack: ()
    legacySwitchExhaustiveness = previousExhaustiveness;
    inferenceLogWriter?.exitStatement(node);
  }

  @override
  void visitSymbolLiteral(
    SymbolLiteral node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    node.visitChildren(this);
    typeAnalyzer.visitSymbolLiteral(node as SymbolLiteralImpl);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitThisExpression(
    ThisExpression node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    node.visitChildren(this);
    typeAnalyzer.visitThisExpression(node as ThisExpressionImpl);
    _insertImplicitCallReference(node, contextType: contextType);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitThrowExpression(
    covariant ThrowExpressionImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    analyzeExpression(
      node.expression,
      SharedTypeSchemaView(typeProvider.objectType),
    );
    popRewrite();
    typeAnalyzer.visitThrowExpression(node);
    flowAnalysis.flow?.handleExit();
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
    elementResolver.visitTopLevelVariableDeclaration(node);
  }

  @override
  void visitTryStatement(covariant TryStatementImpl node) {
    inferenceLogWriter?.enterStatement(node);
    checkUnreachableNode(node);
    var flow = flowAnalysis.flow!;

    var body = node.body;
    var catchClauses = node.catchClauses;
    var finallyBlock = node.finallyBlock;

    if (finallyBlock != null) {
      flow.tryFinallyStatement_bodyBegin();
    }

    if (catchClauses.isNotEmpty) {
      flow.tryCatchStatement_bodyBegin();
    }
    body.accept(this);
    nullSafetyDeadCodeVerifier.flowEnd(node.body);
    nullSafetyDeadCodeVerifier.tryStatementEnter(node);
    if (catchClauses.isNotEmpty) {
      flow.tryCatchStatement_bodyEnd(body);

      var catchLength = catchClauses.length;
      for (var i = 0; i < catchLength; ++i) {
        var catchClause = catchClauses[i];
        nullSafetyDeadCodeVerifier.verifyCatchClause(catchClause);
        // TODO(paulberry): try to remove these casts by changing `node` to a
        // `TryStatementImpl`
        flow.tryCatchStatement_catchBegin(
          catchClause.exceptionParameter?.declaredElement2
              as PromotableElementImpl?,
          catchClause.stackTraceParameter?.declaredElement2
              as PromotableElementImpl?,
        );
        catchClause.accept(this);
        flow.tryCatchStatement_catchEnd();
        nullSafetyDeadCodeVerifier.flowEnd(catchClause.body);
      }

      flow.tryCatchStatement_end();
    }
    nullSafetyDeadCodeVerifier.tryStatementExit(node);

    if (finallyBlock != null) {
      flow.tryFinallyStatement_finallyBegin(
        catchClauses.isNotEmpty ? node : body,
      );
      finallyBlock.accept(this);
      flow.tryFinallyStatement_end();
    }
    inferenceLogWriter?.exitStatement(node);
  }

  @override
  void visitTypeArgumentList(TypeArgumentList node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
  }

  @override
  void visitTypeLiteral(
    covariant TypeLiteralImpl node, {
    TypeImpl contextType = UnknownInferredType.instance,
  }) {
    inferenceLogWriter?.enterExpression(node, contextType);
    checkUnreachableNode(node);
    node.visitChildren(this);
    node.recordStaticType(typeProvider.typeType, resolver: this);
    inferenceLogWriter?.exitExpression(node);
  }

  @override
  void visitTypeParameter(TypeParameter node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
    elementResolver.visitTypeParameter(node);
  }

  @override
  void visitTypeParameterList(TypeParameterList node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
  }

  @override
  void visitVariableDeclaration(covariant VariableDeclarationImpl node) {
    var fragment = node.declaredFragment!;

    libraryResolutionContext._variableNodes[fragment] = node;
    _variableDeclarationResolver.resolve(node);

    var initializer = node.initializer;
    if (initializer != null) {
      var parent = node.parent as VariableDeclarationList;
      var declaredType = parent.type;
      var initializerStaticType = initializer.typeOrThrow;
      flowAnalysis.flow?.initialize(
        node.declaredElement2 as PromotableElementImpl,
        SharedTypeView(initializerStaticType),
        initializer,
        isFinal: parent.isFinal,
        isLate: parent.isLate,
        isImplicitlyTyped: declaredType == null,
      );
    }

    _checkTopLevelCycle(node);
  }

  @override
  void visitVariableDeclarationList(VariableDeclarationList node) {
    flowAnalysis.variableDeclarationList(node);
    checkUnreachableNode(node);
    node.visitChildren(this);
    elementResolver.visitVariableDeclarationList(node);
  }

  @override
  void visitVariableDeclarationStatement(VariableDeclarationStatement node) {
    inferenceLogWriter?.enterStatement(node);
    checkUnreachableNode(node);
    node.visitChildren(this);
    inferenceLogWriter?.exitStatement(node);
  }

  @override
  void visitWhileStatement(covariant WhileStatementImpl node) {
    inferenceLogWriter?.enterStatement(node);
    checkUnreachableNode(node);

    ExpressionImpl condition = node.condition;

    flowAnalysis.flow?.whileStatement_conditionBegin(node);
    analyzeExpression(condition, SharedTypeSchemaView(typeProvider.boolType));
    condition = popRewrite()!;
    var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(condition);

    boolExpressionVerifier.checkForNonBoolCondition(
      node.condition,
      whyNotPromoted: whyNotPromoted,
    );

    flowAnalysis.flow?.whileStatement_bodyBegin(node, condition);
    node.body.accept(this);
    flowAnalysis.flow?.whileStatement_end();
    nullSafetyDeadCodeVerifier.flowEnd(node.body);
    // TODO(brianwilkerson): If the loop can only be exited because the condition
    // is false, then propagateFalseState(condition);
    inferenceLogWriter?.exitStatement(node);
  }

  @override
  void visitWithClause(WithClause node) {
    checkUnreachableNode(node);
    node.visitChildren(this);
  }

  @override
  void visitYieldStatement(covariant YieldStatementImpl node) {
    inferenceLogWriter?.enterStatement(node);
    checkUnreachableNode(node);
    _yieldStatementResolver.resolve(node);
    inferenceLogWriter?.exitStatement(node);
  }

  /// Check whether [errorNode] is an `onError` callback in a
  /// [Future.catchError] call, which might return an implicit `null`.
  void _checkForFutureCatchErrorOnError(BlockFunctionBody errorNode) {
    // Check for "body  might complete normally" in a `Future.catchError`'s
    //`onError` callback.
    var parent = errorNode.parent?.parent;
    if (parent is! ArgumentList) {
      return;
    }
    var invocation = parent.parent;
    if (invocation is! MethodInvocation) {
      return;
    }
    var targetType = invocation.realTarget?.staticType;
    if (invocation.methodName.name == 'catchError' &&
        targetType is InterfaceTypeImpl) {
      var instanceOfFuture = targetType.asInstanceOf2(
        typeProvider.futureElement2,
      );
      if (instanceOfFuture != null) {
        var targetFutureType = instanceOfFuture.typeArguments.first;
        var expectedReturnType = typeProvider.futureOrType(targetFutureType);
        var returnTypeBase = typeSystem.futureOrBase(expectedReturnType);
        if (returnTypeBase is DynamicType ||
            returnTypeBase is UnknownInferredType ||
            returnTypeBase is VoidType ||
            returnTypeBase.isDartCoreNull) {
          return;
        }

        diagnosticReporter.atToken(
          errorNode.block.leftBracket,
          WarningCode.BODY_MIGHT_COMPLETE_NORMALLY_CATCH_ERROR,
          arguments: [returnTypeBase],
        );
      }
    }
  }

  void _checkTopLevelCycle(VariableDeclaration node) {
    var fragment = node.declaredFragment;
    if (fragment is! PropertyInducingFragmentImpl) {
      return;
    }
    // Errors on const are reported separately with
    // [CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT].
    if (fragment.isConst) {
      return;
    }
    var error = fragment.typeInferenceError;
    if (error == null) {
      return;
    }
    if (error.kind == TopLevelInferenceErrorKind.dependencyCycle) {
      var argumentsText = error.arguments.join(', ');
      diagnosticReporter.atToken(
        node.name,
        CompileTimeErrorCode.TOP_LEVEL_CYCLE,
        arguments: [node.name.lexeme, argumentsText],
      );
    }
  }

  /// Creates a union of `T | Future<T>`, unless `T` is already a
  /// future-union, in which case it simply returns `T`.
  TypeImpl _createFutureOr(TypeImpl type) {
    if (type.isDartAsyncFutureOr) {
      return type;
    }
    return typeProvider.futureOrType(type);
  }

  /// Helper function used to print information to the console in debug mode.
  /// This method returns `true` so that it can be conveniently called inside of
  /// an `assert` statement.
  bool _debugPrint(String s) {
    print(s);
    return true;
  }

  TypeImpl _finishFunctionBodyInference() {
    var flow = flowAnalysis.flow;

    return _bodyContext!.computeInferredReturnType(
      endOfBlockIsReachable: flow == null || flow.isReachable,
    );
  }

  /// Infers type arguments corresponding to [typeParameters] used it the
  /// [declaredType], so that thr resulting type is a subtype of [contextType].
  List<TypeImpl> _inferTypeArguments({
    required List<TypeParameterElementImpl> typeParameters,
    required AstNode errorNode,
    required TypeImpl declaredType,
    required TypeImpl contextType,
    required AstNodeImpl? nodeForTesting,
  }) {
    inferenceLogWriter?.enterGenericInference(typeParameters, declaredType);
    var inferrer = GenericInferrer(
      typeSystem,
      typeParameters,
      errorEntity: errorNode,
      genericMetadataIsEnabled: genericMetadataIsEnabled,
      inferenceUsingBoundsIsEnabled: inferenceUsingBoundsIsEnabled,
      strictInference: analysisOptions.strictInference,
      typeSystemOperations: flowAnalysis.typeOperations,
      dataForTesting: inferenceHelper.dataForTesting,
    );
    inferrer.constrainReturnType(
      declaredType,
      contextType,
      nodeForTesting: nodeForTesting,
    );
    return inferrer.chooseFinalTypes();
  }

  /// If `expression` should be treated as `expression.call`, inserts an
  /// [ImplicitCallReference] node which wraps [expression].
  void _insertImplicitCallReference(
    ExpressionImpl expression, {
    required TypeImpl contextType,
  }) {
    var parent = expression.parent;
    if (_shouldSkipImplicitCallReferenceDueToForm(expression, parent)) {
      return;
    }
    var staticType = expression.staticType;
    if (staticType == null) {
      return;
    }
    TypeImpl context;
    if (parent is AssignmentExpressionImpl) {
      if (parent.writeType == null) return;
      context = parent.writeType!;
    } else {
      context = contextType;
    }
    var callMethod = getImplicitCallMethod(staticType, context, expression);
    if (callMethod == null) {
      return;
    }

    // `expression` is to be treated as `expression.call`.
    context = typeSystem.flatten(context);
    var callMethodType = callMethod.type;
    List<DartType> typeArgumentTypes;
    if (isConstructorTearoffsEnabled &&
        callMethodType.typeFormals.isNotEmpty &&
        context is FunctionTypeImpl) {
      typeArgumentTypes = typeSystem.inferFunctionTypeInstantiation(
        context,
        callMethodType,
        diagnosticReporter: diagnosticReporter,
        errorNode: expression,
        // If the constructor-tearoffs feature is enabled, then so is
        // generic-metadata.
        genericMetadataIsEnabled: true,
        inferenceUsingBoundsIsEnabled: inferenceUsingBoundsIsEnabled,
        strictInference: analysisOptions.strictInference,
        strictCasts: analysisOptions.strictCasts,
        typeSystemOperations: flowAnalysis.typeOperations,
        dataForTesting: inferenceHelper.dataForTesting,
        nodeForTesting: expression,
      );
      if (typeArgumentTypes.isNotEmpty) {
        callMethodType = callMethodType.instantiate(typeArgumentTypes);
      }
    } else {
      typeArgumentTypes = [];
    }

    var callReference = ImplicitCallReferenceImpl(
      expression: expression,
      element: callMethod,
      typeArguments: null,
      typeArgumentTypes: typeArgumentTypes,
    );
    replaceExpression(expression, callReference, parent: parent);

    callReference.setPseudoExpressionStaticType(callMethodType);
  }

  void _resolvePropertyAccessRhs(
    PropertyAccessImpl node,
    TypeImpl contextType,
  ) {
    if (node.isNullAware) {
      _startNullAwareAccess(node, node.target);
      nullSafetyDeadCodeVerifier.visitNode(node.propertyName);
    }

    var result = _propertyElementResolver.resolvePropertyAccess(
      node: node,
      hasRead: true,
      hasWrite: false,
    );

    _resolvePropertyAccessRhs_common(
      result,
      node,
      node.propertyName,
      contextType,
    );
    nullSafetyDeadCodeVerifier.verifyPropertyAccess(node);
  }

  /// Common logic for resolving dot shorthands property accesses and
  /// [_resolvePropertyAccessRhs].
  void _resolvePropertyAccessRhs_common(
    PropertyElementResolverResult resolverResult,
    ExpressionImpl node,
    SimpleIdentifierImpl propertyName,
    TypeImpl contextType,
  ) {
    var element = resolverResult.readElement2;

    propertyName.element = element;

    DartType type;
    if (element is MethodElement) {
      type = element.type;
    } else if (element is ConstructorElementMixin2) {
      type = element.type;
    } else if (element is GetterElement) {
      type = resolverResult.getType!;
    } else if (resolverResult.functionTypeCallType != null) {
      type = resolverResult.functionTypeCallType!;
    } else if (resolverResult.recordField != null) {
      type = resolverResult.recordField!.type;
    } else if (resolverResult.atDynamicTarget) {
      type = DynamicTypeImpl.instance;
    } else {
      type = InvalidTypeImpl.instance;
    }

    if (!isConstructorTearoffsEnabled) {
      // Only perform a generic function instantiation on a [PrefixedIdentifier]
      // in pre-constructor-tearoffs code. In constructor-tearoffs-enabled code,
      // generic function instantiation is performed at assignability check
      // sites.
      // TODO(srawlins): Switch all resolution to use the latter method, in a
      // breaking change release.
      type = inferenceHelper.inferTearOff(
        node,
        propertyName,
        type,
        contextType: contextType,
      );
    }

    propertyName.setPseudoExpressionStaticType(type);
    node.recordStaticType(type, resolver: this);
    var replacement = insertGenericFunctionInstantiation(
      node,
      contextType: contextType,
    );

    nullShortingTermination(node, rewrittenExpression: replacement);
    _insertImplicitCallReference(replacement, contextType: contextType);
  }

  /// Continues resolution of a [FunctionExpressionInvocation] that was created
  /// from a rewritten [MethodInvocation]. The target function is already
  /// resolved.
  ///
  /// The specification says that `target.getter()` should be treated as an
  /// ordinary method invocation. So, we need to perform the same null shorting
  /// as for method invocations.
  void _resolveRewrittenFunctionExpressionInvocation(
    FunctionExpressionInvocationImpl node,
    List<WhyNotPromotedGetter> whyNotPromotedArguments, {
    required TypeImpl contextType,
  }) {
    var function = node.function;

    if (function is PropertyAccessImpl && function.isNullAware) {
      _startNullAwareAccess(function, function.target);
      nullSafetyDeadCodeVerifier.visitNode(node.argumentList);
    }

    _functionExpressionInvocationResolver.resolve(
      node,
      whyNotPromotedArguments,
      contextType: contextType,
    );

    nullShortingTermination(node);
  }

  void _setupThisType() {
    var enclosingClass = this.enclosingClass;
    if (enclosingClass != null) {
      _thisType = enclosingClass.thisType;
    } else {
      var enclosingExtension = this.enclosingExtension;
      if (enclosingExtension != null) {
        _thisType = enclosingExtension.extendedType;
      }
    }
  }

  bool _shouldSkipImplicitCallReferenceDueToForm(
    Expression expression,
    AstNode? parent,
  ) {
    while (parent is ParenthesizedExpression) {
      expression = parent;
      parent = expression.parent;
    }
    if (parent is CascadeExpression && parent.target == expression) {
      // Do not perform an "implicit tear-off conversion" here. It should only
      // be performed on [parent]. See
      // https://github.com/dart-lang/language/issues/1873.
      return true;
    }
    if (parent is ConditionalExpression &&
        (parent.thenExpression == expression ||
            parent.elseExpression == expression)) {
      // Do not perform an "implicit tear-off conversion" on the branches of a
      // conditional expression.
      return true;
    }
    if (parent is BinaryExpression &&
        parent.operator.type == TokenType.QUESTION_QUESTION) {
      // Do not perform an "implicit tear-off conversion" on the branches of a
      // `??` operator.
      return true;
    }
    return false;
  }

  void _startNullAwareAccess(
    NullShortableExpression node,
    ExpressionImpl? target,
  ) {
    var flow = flowAnalysis.flow;
    if (flow != null) {
      switch (target) {
        case null:
          // This means the property access target is the target of a cascade.
          // For this case, `node.isNullAware=true` means that the cascade is
          // null aware, but that has already been taken care of in
          // `visitCascadeExpression`. So there is nothing further to do.
          break;
        case SimpleIdentifier(element: InterfaceElement()):
          // `?.` to access static methods is equivalent to `.`, so do nothing.
          break;
        case ExtensionOverride(
          argumentList: ArgumentListImpl(arguments: [var expression]),
        ):
        case var expression:
          flow.nullAwareAccess_rightBegin(
            expression,
            SharedTypeView(expression.staticType ?? typeProvider.dynamicType),
          );
          _unfinishedNullShorts.add(node.nullShortingTermination);
      }
    }
  }

  /// Given an [argumentList] and the [parameters] related to the element that
  /// will be invoked using those arguments, compute the list of parameters that
  /// correspond to the list of arguments.
  ///
  /// Returns the parameters that correspond to the arguments. If no parameter
  /// matched an argument, that position will be `null` in the list.
  static List<FormalParameterElementMixin?> resolveArgumentsToParameters({
    required ArgumentList argumentList,
    required List<FormalParameterElement> formalParameters,
    DiagnosticReporter? diagnosticReporter,
    ConstructorDeclaration? enclosingConstructor,
  }) {
    int requiredParameterCount = 0;
    int unnamedParameterCount = 0;
    var unnamedParameters = <FormalParameterElementMixin>[];
    Map<String, FormalParameterElementMixin>? namedParameters;
    int length = formalParameters.length;
    for (int i = 0; i < length; i++) {
      var parameter = formalParameters[i] as FormalParameterElementMixin;
      if (parameter.isRequiredPositional) {
        unnamedParameters.add(parameter);
        unnamedParameterCount++;
        requiredParameterCount++;
      } else if (parameter.isOptionalPositional) {
        unnamedParameters.add(parameter);
        unnamedParameterCount++;
      } else {
        namedParameters ??= {};
        namedParameters[parameter.name3 ?? ''] = parameter;
      }
    }
    int unnamedIndex = 0;
    NodeList<Expression> arguments = argumentList.arguments;
    int argumentCount = arguments.length;
    var resolvedParameters = List<FormalParameterElementMixin?>.filled(
      argumentCount,
      null,
    );
    int positionalArgumentCount = 0;
    bool noBlankArguments = true;
    Expression? firstUnresolvedArgument;
    Expression? lastPositionalArgument;
    for (int i = 0; i < argumentCount; i++) {
      Expression argument = arguments[i];
      if (argument is! NamedExpression) {
        if (argument is SimpleIdentifier && argument.name.isEmpty) {
          noBlankArguments = false;
        }
        positionalArgumentCount++;
        if (unnamedIndex < unnamedParameterCount) {
          resolvedParameters[i] = unnamedParameters[unnamedIndex++];
        } else {
          firstUnresolvedArgument ??= argument;
        }
        lastPositionalArgument = argument;
      }
    }

    Set<String>? usedNames;
    if (enclosingConstructor != null) {
      var result = verifySuperFormalParameters(
        constructor: enclosingConstructor,
        hasExplicitPositionalArguments: positionalArgumentCount != 0,
        diagnosticReporter: diagnosticReporter,
      );
      positionalArgumentCount += result.positionalArgumentCount;
      if (result.namedArgumentNames.isNotEmpty) {
        usedNames = result.namedArgumentNames.toSet();
      }
    }

    for (int i = 0; i < argumentCount; i++) {
      Expression argument = arguments[i];
      if (argument is NamedExpressionImpl) {
        var nameNode = argument.name.label;
        String name = nameNode.name;
        var element = namedParameters != null ? namedParameters[name] : null;
        if (element == null) {
          diagnosticReporter?.atNode(
            nameNode,
            CompileTimeErrorCode.UNDEFINED_NAMED_PARAMETER,
            arguments: [name],
          );
        } else {
          resolvedParameters[i] = element;
          nameNode.element = element;
        }
        usedNames ??= <String>{};
        if (!usedNames.add(name)) {
          diagnosticReporter?.atNode(
            nameNode,
            CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT,
            arguments: [name],
          );
        }
      }
    }

    if (positionalArgumentCount < requiredParameterCount && noBlankArguments) {
      var parent = argumentList.parent;
      if (diagnosticReporter != null && parent != null) {
        var token =
            lastPositionalArgument?.endToken.next ??
            argumentList.leftParenthesis.next ??
            argumentList.rightParenthesis;
        _reportNotEnoughPositionalArguments(
          token: token,
          requiredParameterCount: requiredParameterCount,
          actualArgumentCount: positionalArgumentCount,
          nameNode: parent,
          diagnosticReporter: diagnosticReporter,
        );
      }
    } else if (positionalArgumentCount > unnamedParameterCount &&
        noBlankArguments) {
      DiagnosticCode diagnosticCode;
      int namedParameterCount = namedParameters?.length ?? 0;
      int namedArgumentCount = usedNames?.length ?? 0;
      if (namedParameterCount > namedArgumentCount) {
        diagnosticCode =
            CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED;
      } else {
        diagnosticCode = CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS;
      }
      if (firstUnresolvedArgument != null) {
        diagnosticReporter?.atNode(
          firstUnresolvedArgument,
          diagnosticCode,
          arguments: [unnamedParameterCount, positionalArgumentCount],
        );
      }
    }
    return resolvedParameters;
  }

  /// Debug-only: verifies that [list] is a modifiable list by setting its
  /// length to itself.
  ///
  /// For a normal list this is a no-op; for an unmodifiable (i.e. const) list,
  /// this will cause an exception to be thrown.
  static bool _isModifiableList(List<Object?> list) {
    try {
      list.length = list.length;
    } catch (_) {
      return false;
    }
    return true;
  }

  /// Reports [CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS_SINGULAR] or
  /// [CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS_PLURAL] at the
  /// specified [token], considering the name of the [nameNode].
  static void _reportNotEnoughPositionalArguments({
    required Token token,
    required int requiredParameterCount,
    required int actualArgumentCount,
    required AstNode nameNode,
    required DiagnosticReporter diagnosticReporter,
  }) {
    String? name;
    if (nameNode is InstanceCreationExpression) {
      var constructorName = nameNode.constructorName;
      name =
          constructorName.name?.name ??
          '${constructorName.type.name.lexeme}.new';
    } else if (nameNode is RedirectingConstructorInvocation) {
      name = nameNode.constructorName?.name;
      if (name == null) {
        var element = nameNode.element;
        if (element != null) {
          name = '${element.returnType.getDisplayString()}.new';
        }
      }
    } else if (nameNode is SuperConstructorInvocation) {
      name = nameNode.constructorName?.name;
      if (name == null) {
        var element = nameNode.element;
        if (element != null) {
          name = '${element.returnType.getDisplayString()}.new';
        }
      }
    } else if (nameNode is MethodInvocation) {
      name = nameNode.methodName.name;
    } else if (nameNode is FunctionExpressionInvocation) {
      var function = nameNode.function;
      if (function is SimpleIdentifier) {
        name = function.name;
      }
    } else if (nameNode is EnumConstantArguments) {
      var parent = nameNode.parent;
      if (parent is EnumConstantDeclaration) {
        var declaredElement = parent.declaredFragment!.element;
        name = declaredElement.type.getDisplayString();
      }
    } else if (nameNode is EnumConstantDeclaration) {
      var declaredElement = nameNode.declaredFragment!.element;
      name = declaredElement.type.getDisplayString();
    } else if (nameNode is Annotation) {
      var nameNodeName = nameNode.name;
      name =
          nameNodeName is PrefixedIdentifier
              ? nameNodeName.identifier.name
              : '${nameNodeName.name}.new';
    } else if (nameNode is DotShorthandConstructorInvocation) {
      name = nameNode.constructorName.name;
    } else if (nameNode is DotShorthandInvocation) {
      name = nameNode.memberName.name;
    } else {
      throw UnimplementedError('(${nameNode.runtimeType}) $nameNode');
    }

    var isPlural = requiredParameterCount > 1;
    var arguments = <Object>[];
    if (isPlural) {
      arguments.add(requiredParameterCount);
      arguments.add(actualArgumentCount);
    }
    DiagnosticCode diagnosticCode;
    if (name == null) {
      diagnosticCode =
          isPlural
              ? CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS_PLURAL
              : CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS_SINGULAR;
    } else {
      diagnosticCode =
          isPlural
              ? CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS_NAME_PLURAL
              : CompileTimeErrorCode
                  .NOT_ENOUGH_POSITIONAL_ARGUMENTS_NAME_SINGULAR;
      arguments.add(name);
    }
    diagnosticReporter.atToken(token, diagnosticCode, arguments: arguments);
  }
}

/// Instances of the class `ScopeResolverVisitor` are used to resolve
/// [SimpleIdentifier]s to declarations using scoping rules.
///
// TODO(paulberry): migrate the responsibility for all scope resolution into
// this visitor.
class ScopeResolverVisitor extends UnifyingAstVisitor<void> {
  /// The diagnostic reporter that will be informed of any diagnostics that are
  /// found during resolution.
  final DiagnosticReporter diagnosticReporter;

  /// The scope used to resolve identifiers.
  Scope nameScope;

  /// The scope of libraries imported by `@docImport`s.
  final DocumentationCommentScope _docImportScope;

  /// The scope used to resolve unlabeled `break` and `continue` statements.
  ImplicitLabelScope _implicitLabelScope = ImplicitLabelScope.ROOT;

  /// The scope used to resolve labels for `break` and `continue` statements, or
  /// `null` if no labels have been defined in the current context.
  LabelScope? _labelScope;

  /// The container with information about local variables.
  final LocalVariableInfo _localVariableInfo = LocalVariableInfo();

  /// If the current function is contained within a closure (a local function or
  /// function expression inside another executable declaration), the element
  /// representing the closure; otherwise `null`.
  LocalFunctionElement? _enclosingClosure;

  /// Initialize a newly created visitor to resolve the nodes in an AST node.
  ///
  /// [diagnosticReporter] is the error reporter that will be informed of any errors
  /// that are found during resolution.
  /// [nameScope] is the scope used to resolve identifiers in the node that will
  /// first be visited.
  ScopeResolverVisitor(
    this.diagnosticReporter, {
    required this.nameScope,
    List<LibraryElement> docImportLibraries = const [],
  }) : _docImportScope = DocumentationCommentScope(
         nameScope,
         docImportLibraries,
       );

  /// Return the implicit label scope in which the current node is being
  /// resolved.
  ImplicitLabelScope get implicitLabelScope => _implicitLabelScope;

  @override
  void visitAssignedVariablePattern(AssignedVariablePattern node) {
    var element = node.element2;
    if (element is PromotableElement) {
      _localVariableInfo.potentiallyMutatedInScope.add(element);
    }
  }

  @override
  void visitBlock(covariant BlockImpl node) {
    _withDeclaredLocals(node, node.statements, () {
      super.visitBlock(node);
    });
  }

  @override
  void visitBlockFunctionBody(BlockFunctionBody node) {
    ImplicitLabelScope implicitOuterScope = _implicitLabelScope;
    try {
      _implicitLabelScope = ImplicitLabelScope.ROOT;
      super.visitBlockFunctionBody(node);
    } finally {
      _implicitLabelScope = implicitOuterScope;
    }
  }

  @override
  void visitBreakStatement(covariant BreakStatementImpl node) {
    node.target = _lookupBreakOrContinueTarget(node, node.label, false);
  }

  @override
  void visitCatchClause(CatchClause node) {
    var exception = node.exceptionParameter;
    if (exception != null) {
      Scope outerScope = nameScope;
      try {
        nameScope = LocalScope(nameScope);
        _define(exception.declaredElement2!);
        var stackTrace = node.stackTraceParameter;
        if (stackTrace != null) {
          _define(stackTrace.declaredElement2!);
        }
        super.visitCatchClause(node);
      } finally {
        nameScope = outerScope;
      }
    } else {
      super.visitCatchClause(node);
    }
  }

  @override
  void visitClassDeclaration(covariant ClassDeclarationImpl node) {
    Scope outerScope = nameScope;
    try {
      var element = node.declaredFragment!.element;
      node.metadata.accept(this);

      nameScope = TypeParameterScope(nameScope, element.typeParameters2);
      node.nameScope = nameScope;
      node.typeParameters?.accept(this);
      node.extendsClause?.accept(this);
      node.withClause?.accept(this);
      node.implementsClause?.accept(this);
      node.nativeClause?.accept(this);

      nameScope = InstanceScope(nameScope, element);
      _visitDocumentationComment(node.documentationComment);
      node.members.accept(this);
    } finally {
      nameScope = outerScope;
    }
  }

  @override
  void visitClassTypeAlias(covariant ClassTypeAliasImpl node) {
    node.metadata.accept(this);
    Scope outerScope = nameScope;
    try {
      var element = node.declaredFragment!.element;
      nameScope = InstanceScope(
        TypeParameterScope(nameScope, element.typeParameters2),
        element,
      );
      _visitDocumentationComment(node.documentationComment);
      node.typeParameters?.accept(this);
      node.superclass.accept(this);
      node.withClause.accept(this);
      node.implementsClause?.accept(this);
    } finally {
      nameScope = outerScope;
    }
  }

  @override
  void visitCompilationUnit(covariant CompilationUnitImpl node) {
    node.nameScope = nameScope;
    super.visitCompilationUnit(node);
  }

  @override
  void visitConstructorDeclaration(covariant ConstructorDeclarationImpl node) {
    node.body.localVariableInfo = _localVariableInfo;
    Scope outerScope = nameScope;
    try {
      var element = node.declaredFragment!.element;

      node.metadata.accept(this);
      node.returnType.accept(this);
      node.parameters.accept(this);

      try {
        nameScope = ConstructorInitializerScope(nameScope, element);
        node.initializers.accept(this);
        _visitDocumentationComment(node.documentationComment);
      } finally {
        nameScope = outerScope;
      }

      node.redirectedConstructor?.accept(this);

      nameScope = FormalParameterScope(nameScope, element.formalParameters);
      node.body.accept(this);
    } finally {
      nameScope = outerScope;
    }
  }

  @override
  void visitContinueStatement(covariant ContinueStatementImpl node) {
    node.target = _lookupBreakOrContinueTarget(node, node.label, true);
  }

  @override
  void visitDeclaredIdentifier(DeclaredIdentifier node) {
    _define(node.declaredFragment!.element);
    super.visitDeclaredIdentifier(node);
  }

  @override
  void visitDoStatement(DoStatement node) {
    ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
    try {
      _implicitLabelScope = _implicitLabelScope.nest(node);
      _visitStatementInScope(node.body);
      node.condition.accept(this);
    } finally {
      _implicitLabelScope = outerImplicitScope;
    }
  }

  @override
  void visitEnumConstantDeclaration(
    covariant EnumConstantDeclarationImpl node,
  ) {
    node.metadata.accept(this);
    _visitDocumentationComment(node.documentationComment);
    node.arguments?.accept(this);
  }

  @override
  void visitEnumDeclaration(covariant EnumDeclarationImpl node) {
    Scope outerScope = nameScope;
    try {
      var element = node.declaredFragment!.element;
      node.metadata.accept(this);

      nameScope = TypeParameterScope(nameScope, element.typeParameters2);
      node.nameScope = nameScope;
      node.typeParameters?.accept(this);
      node.withClause?.accept(this);
      node.implementsClause?.accept(this);

      nameScope = InstanceScope(nameScope, element);
      _visitDocumentationComment(node.documentationComment);
      node.constants.accept(this);
      node.members.accept(this);
    } finally {
      nameScope = outerScope;
    }
  }

  @override
  void visitExpressionFunctionBody(covariant ExpressionFunctionBodyImpl node) {
    node.nameScope = nameScope;
    super.visitExpressionFunctionBody(node);
  }

  @override
  void visitExtensionDeclaration(covariant ExtensionDeclarationImpl node) {
    var outerScope = nameScope;
    try {
      var element = node.declaredFragment!.element;
      node.metadata.accept(this);

      nameScope = TypeParameterScope(nameScope, element.typeParameters2);
      node.nameScope = nameScope;
      node.typeParameters?.accept(this);
      node.onClause?.accept(this);

      nameScope = ExtensionScope(nameScope, element);
      _visitDocumentationComment(node.documentationComment);
      node.members.accept(this);
    } finally {
      nameScope = outerScope;
    }
  }

  @override
  void visitExtensionTypeDeclaration(
    covariant ExtensionTypeDeclarationImpl node,
  ) {
    Scope outerScope = nameScope;
    try {
      var element = node.declaredFragment!.element;
      node.metadata.accept(this);

      nameScope = TypeParameterScope(nameScope, element.typeParameters2);
      node.nameScope = nameScope;
      node.typeParameters?.accept(this);
      node.representation.accept(this);
      node.implementsClause?.accept(this);

      nameScope = InstanceScope(nameScope, element);
      _visitDocumentationComment(node.documentationComment);
      node.members.accept(this);
    } finally {
      nameScope = outerScope;
    }
  }

  @override
  void visitFieldDeclaration(covariant FieldDeclarationImpl node) {
    node.metadata.accept(this);
    _visitDocumentationComment(node.documentationComment);
    node.fields.accept(this);
  }

  @override
  void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
    // We visit the iterator before the loop variable because the loop variable
    // cannot be in scope while visiting the iterator.
    node.iterable.accept(this);
    node.loopVariable.accept(this);
  }

  @override
  void visitForEachPartsWithPattern(
    covariant ForEachPartsWithPatternImpl node,
  ) {
    // We visit the iterator before the pattern because the pattern variables
    // cannot be in scope while visiting the iterator.
    node.iterable.accept(this);

    for (var variable in node.variables) {
      _define(variable.asElement2);
    }

    node.pattern.accept(this);
  }

  @override
  void visitForElement(covariant ForElementImpl node) {
    Scope outerNameScope = nameScope;
    try {
      nameScope = LocalScope(nameScope);
      node.nameScope = nameScope;
      node.forLoopParts.accept(this);
      node.body.accept(this);
    } finally {
      nameScope = outerNameScope;
    }
  }

  @override
  void visitFormalParameterList(FormalParameterList node) {
    super.visitFormalParameterList(node);
    // We finished resolving function signature, now include formal parameters
    // scope.  Note: we must not do this if the parent is a
    // FunctionTypedFormalParameter, because in that case we aren't finished
    // resolving the full function signature, just a part of it.
    var parent = node.parent;
    if (parent is FunctionExpression) {
      var element = parent.declaredFragment!.element;
      nameScope = FormalParameterScope(nameScope, element.formalParameters);
    } else if (parent is FunctionTypeAlias) {
      var aliasedElement = parent.declaredFragment!.element.aliasedElement2;
      var functionElement = aliasedElement as GenericFunctionTypeElement;
      nameScope = FormalParameterScope(
        nameScope,
        functionElement.formalParameters,
      );
    } else if (parent is MethodDeclaration) {
      var element = parent.declaredFragment!.element;
      nameScope = FormalParameterScope(nameScope, element.formalParameters);
    }
  }

  @override
  void visitForStatement(covariant ForStatementImpl node) {
    Scope outerNameScope = nameScope;
    ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
    try {
      nameScope = LocalScope(nameScope);
      _implicitLabelScope = _implicitLabelScope.nest(node);
      node.nameScope = nameScope;
      node.forLoopParts.accept(this);
      _visitStatementInScope(node.body);
    } finally {
      nameScope = outerNameScope;
      _implicitLabelScope = outerImplicitScope;
    }
  }

  @override
  void visitFunctionDeclaration(covariant FunctionDeclarationImpl node) {
    node.functionExpression.body.localVariableInfo = _localVariableInfo;
    var outerClosure = _enclosingClosure;
    Scope outerScope = nameScope;
    try {
      var element = node.declaredFragment!.element;
      _enclosingClosure = element.ifTypeOrNull<LocalFunctionElement>();
      node.metadata.accept(this);
      nameScope = TypeParameterScope(nameScope, element.typeParameters2);
      node.nameScope = nameScope;
      node.returnType?.accept(this);
      node.functionExpression.accept(this);
    } finally {
      nameScope = outerScope;
      _enclosingClosure = outerClosure;
    }
  }

  @override
  void visitFunctionExpression(FunctionExpression node) {
    var outerClosure = _enclosingClosure;
    Scope outerScope = nameScope;
    try {
      var element = node.declaredFragment!.element;
      if (node.parent is! FunctionDeclaration) {
        (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
        _enclosingClosure = element as LocalFunctionElement;
      }
      var parent = node.parent;
      if (parent is FunctionDeclarationImpl) {
        // We have already created a function scope and don't need to do so again.
        super.visitFunctionExpression(node);
        _visitDocumentationComment(parent.documentationComment);
        return;
      }

      nameScope = FormalParameterScope(
        TypeParameterScope(nameScope, element.typeParameters2),
        element.formalParameters,
      );
      super.visitFunctionExpression(node);
    } finally {
      nameScope = outerScope;
      _enclosingClosure = outerClosure;
    }
  }

  @override
  void visitFunctionTypeAlias(covariant FunctionTypeAliasImpl node) {
    node.metadata.accept(this);
    Scope outerScope = nameScope;
    try {
      var element = node.declaredFragment!.element;
      nameScope = TypeParameterScope(nameScope, element.typeParameters2);
      node.returnType?.accept(this);
      node.typeParameters?.accept(this);
      node.parameters.accept(this);
      // Visiting the parameters added them to the scope as a side effect. So it
      // is safe to visit the documentation comment now.
      _visitDocumentationComment(node.documentationComment);
    } finally {
      nameScope = outerScope;
    }
  }

  @override
  void visitFunctionTypedFormalParameter(
    covariant FunctionTypedFormalParameterImpl node,
  ) {
    node.metadata.accept(this);
    Scope outerScope = nameScope;
    try {
      var element = node.declaredFragment!.element;
      nameScope = TypeParameterScope(nameScope, element.typeParameters2);
      _visitDocumentationComment(node.documentationComment);
      node.returnType?.accept(this);
      node.typeParameters?.accept(this);
      node.parameters.accept(this);
    } finally {
      nameScope = outerScope;
    }
  }

  @override
  void visitGenericFunctionType(covariant GenericFunctionTypeImpl node) {
    var type = node.type;
    if (type == null) {
      // The function type hasn't been resolved yet, so we can't create a scope
      // for its parameters.
      super.visitGenericFunctionType(node);
      return;
    }

    Scope outerScope = nameScope;
    try {
      var element = node.declaredFragment!.element;
      nameScope = TypeParameterScope(nameScope, element.typeParameters2);
      node.nameScope = nameScope;
      super.visitGenericFunctionType(node);
    } finally {
      nameScope = outerScope;
    }
  }

  @override
  void visitGenericTypeAlias(covariant GenericTypeAliasImpl node) {
    node.metadata.accept(this);
    Scope outerScope = nameScope;
    try {
      var element = node.declaredFragment!.element;
      nameScope = TypeParameterScope(nameScope, element.typeParameters2);
      node.nameScope = nameScope;
      node.typeParameters?.accept(this);
      node.type.accept(this);

      var aliasedElement = element.aliasedElement2;
      if (aliasedElement is GenericFunctionTypeElement) {
        nameScope = FormalParameterScope(
          TypeParameterScope(nameScope, aliasedElement.typeParameters2),
          aliasedElement.formalParameters,
        );
      }
      _visitDocumentationComment(node.documentationComment);
    } finally {
      nameScope = outerScope;
    }
  }

  @override
  void visitGuardedPattern(covariant GuardedPatternImpl node) {
    var patternVariables = node.variables.values.toList();
    for (var variable in patternVariables) {
      _define(variable);
    }

    node.pattern.accept(this);

    for (var variable in patternVariables) {
      variable.isVisitingWhenClause = true;
    }

    node.whenClause?.accept(this);

    for (var variable in patternVariables) {
      variable.isVisitingWhenClause = false;
    }
  }

  @override
  void visitHideCombinator(HideCombinator node) {
    var scope = nameScope.ifTypeOrNull<LibraryFragmentScope>();
    scope?.importsTrackingActive(false);
    try {
      super.visitHideCombinator(node);
    } finally {
      scope?.importsTrackingActive(true);
    }
  }

  @override
  void visitIfElement(covariant IfElementImpl node) {
    _visitIf(node);
  }

  @override
  void visitIfStatement(covariant IfStatementImpl node) {
    _visitIf(node);
  }

  @override
  void visitLabeledStatement(LabeledStatement node) {
    var outerScope = _addScopesFor(node.labels, node.unlabeled);
    try {
      super.visitLabeledStatement(node);
    } finally {
      _labelScope = outerScope;
    }
  }

  @override
  void visitLibraryDirective(covariant LibraryDirectiveImpl node) {
    node.metadata.accept(this);
    _visitDocumentationComment(node.documentationComment);
  }

  @override
  void visitLibraryIdentifier(LibraryIdentifier node) {}

  @override
  void visitMethodDeclaration(covariant MethodDeclarationImpl node) {
    node.body.localVariableInfo = _localVariableInfo;
    node.metadata.accept(this);
    Scope outerScope = nameScope;
    try {
      var element = node.declaredFragment!.element;
      nameScope = TypeParameterScope(nameScope, element.typeParameters2);
      node.nameScope = nameScope;
      node.returnType?.accept(this);
      node.typeParameters?.accept(this);
      node.parameters?.accept(this);
      // Visiting the parameters added them to the scope as a side effect. So it
      // is safe to visit the documentation comment now.
      _visitDocumentationComment(node.documentationComment);
      node.body.accept(this);
    } finally {
      nameScope = outerScope;
    }
  }

  @override
  void visitMethodInvocation(MethodInvocation node) {
    // Only visit the method name if there's no real target (so this is an
    // unprefixed function invocation, outside a cascade).  This is the only
    // circumstance in which the method name is meant to be looked up in the
    // current scope.
    node.target?.accept(this);
    if (node.realTarget == null) {
      node.methodName.accept(this);
    }
    node.typeArguments?.accept(this);
    node.argumentList.accept(this);
  }

  @override
  void visitMixinDeclaration(covariant MixinDeclarationImpl node) {
    Scope outerScope = nameScope;
    try {
      var element = node.declaredFragment!.element;
      node.metadata.accept(this);

      nameScope = TypeParameterScope(nameScope, element.typeParameters2);
      node.nameScope = nameScope;
      node.typeParameters?.accept(this);
      node.onClause?.accept(this);
      node.implementsClause?.accept(this);

      nameScope = InstanceScope(nameScope, element);
      _visitDocumentationComment(node.documentationComment);
      node.members.accept(this);
    } finally {
      nameScope = outerScope;
    }
  }

  @override
  void visitNamedType(NamedType node) {
    // All TypeName(s) are already resolved, so we don't resolve it here.
    // But there might be type arguments with Expression(s), such as
    // annotations on formal parameters of GenericFunctionType(s).
    node.typeArguments?.accept(this);
  }

  @override
  void visitPatternVariableDeclaration(
    covariant PatternVariableDeclarationImpl node,
  ) {
    for (var variable in node.elements) {
      _define(variable);
    }

    super.visitPatternVariableDeclaration(node);
  }

  @override
  void visitPrefixedIdentifier(PrefixedIdentifier node) {
    // Do not visit the identifier after the `.`, since it is not meant to be
    // looked up in the current scope.
    node.prefix.accept(this);
  }

  @override
  void visitPropertyAccess(PropertyAccess node) {
    // Do not visit the property name, since it is not meant to be looked up in
    // the current scope.
    node.target?.accept(this);
  }

  @override
  void visitShowCombinator(ShowCombinator node) {
    var scope = nameScope.ifTypeOrNull<LibraryFragmentScope>();
    scope?.importsTrackingActive(false);
    try {
      super.visitShowCombinator(node);
    } finally {
      scope?.importsTrackingActive(true);
    }
  }

  @override
  void visitSimpleIdentifier(covariant SimpleIdentifierImpl node) {
    // Ignore if already resolved - declaration or type.
    if (node.inDeclarationContext()) {
      return;
    }
    // Ignore if qualified.
    var parent = node.parent;
    if (parent is ConstructorName && parent.name == node) {
      return;
    }
    if (parent is Label && parent.parent is NamedExpression) {
      return;
    }
    var scopeLookupResult = nameScope.lookup(node.name);
    node.scopeLookupResult = scopeLookupResult;
    // Ignore if it cannot be a reference to a local variable.
    if (parent is FieldFormalParameter) {
      return;
    } else if (parent is ConstructorDeclaration && parent.returnType == node) {
      return;
    } else if (parent is ConstructorFieldInitializer &&
        parent.fieldName == node) {
      return;
    }
    if (parent is Label) {
      return;
    }
    // Prepare VariableElement.
    var element = scopeLookupResult.getter2;
    if (element is! VariableElement) {
      return;
    }
    // Must be local or parameter.
    ElementKind kind = element.kind;
    if (kind == ElementKind.LOCAL_VARIABLE || kind == ElementKind.PARAMETER) {
      node.element = element;
      if (node.inSetterContext()) {
        if (element is PatternVariableElementImpl &&
            element.isVisitingWhenClause) {
          diagnosticReporter.atNode(
            node,
            CompileTimeErrorCode.PATTERN_VARIABLE_ASSIGNMENT_INSIDE_GUARD,
          );
        }
        _localVariableInfo.potentiallyMutatedInScope.add(element);
      }
    }
    if (element is JoinPatternVariableElementImpl) {
      element.references.add(node);
    }
  }

  @override
  void visitSwitchExpression(covariant SwitchExpressionImpl node) {
    node.expression.accept(this);

    for (var case_ in node.cases) {
      _withNameScope(() {
        case_.nameScope = nameScope;
        var guardedPattern = case_.guardedPattern;
        var variables = guardedPattern.variables;
        for (var variable in variables.values) {
          _define(variable);
        }
        case_.accept(this);
      });
    }
  }

  @override
  void visitSwitchStatement(covariant SwitchStatementImpl node) {
    var outerScope = _labelScope;
    var outerImplicitScope = _implicitLabelScope;
    try {
      _implicitLabelScope = _implicitLabelScope.nest(node);
      for (var member in node.members) {
        for (var label in member.labels) {
          var labelName = label.label;
          var labelElement = labelName.element as LabelElement;
          _labelScope = LabelScope(
            _labelScope,
            labelName.name,
            member,
            labelElement,
          );
        }
      }
      node.expression.accept(this);
      for (var group in node.memberGroups) {
        for (var member in group.members) {
          if (member is SwitchCaseImpl) {
            member.expression.accept(this);
          } else if (member is SwitchPatternCaseImpl) {
            _withNameScope(() {
              member.guardedPattern.accept(this);
            });
          }
        }
        if (group.members.isEmpty) {
          return;
        }
        var lastMember = group.members.last;
        _withDeclaredLocals(lastMember, lastMember.statements, () {
          for (var variable in group.variables.values) {
            _define(variable);
          }
          lastMember.statements.accept(this);
        });
      }
    } finally {
      _labelScope = outerScope;
      _implicitLabelScope = outerImplicitScope;
    }
  }

  @override
  void visitTopLevelVariableDeclaration(
    covariant TopLevelVariableDeclarationImpl node,
  ) {
    node.metadata.accept(this);
    _visitDocumentationComment(node.documentationComment);
    node.variables.accept(this);
  }

  @override
  void visitVariableDeclaration(VariableDeclaration node) {
    super.visitVariableDeclaration(node);

    if (node.parent!.parent is ForParts) {
      _define(node.declaredElement2!);
    }
  }

  @override
  void visitWhileStatement(WhileStatement node) {
    node.condition.accept(this);
    ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
    try {
      _implicitLabelScope = _implicitLabelScope.nest(node);
      _visitStatementInScope(node.body);
    } finally {
      _implicitLabelScope = outerImplicitScope;
    }
  }

  /// Adds scopes for each of the given [labels].
  ///
  /// Returns the scope that was in effect before the new scopes were added.
  LabelScope? _addScopesFor(NodeList<Label> labels, AstNode node) {
    var outerScope = _labelScope;
    for (var label in labels) {
      var labelNameNode = label.label;
      var labelName = labelNameNode.name;
      var labelElement = labelNameNode.element as LabelElement;
      _labelScope = LabelScope(_labelScope, labelName, node, labelElement);
    }
    return outerScope;
  }

  void _define(Element element) {
    (nameScope as LocalScope).add(element);
  }

  /// Return the target of a break or continue statement, and update the static
  /// element of its label (if any). The [parentNode] is the AST node of the
  /// break or continue statement. The [labelNode] is the label contained in
  /// that statement (if any). The flag [isContinue] is `true` if the node being
  /// visited is a continue statement.
  AstNode? _lookupBreakOrContinueTarget(
    AstNode parentNode,
    SimpleIdentifierImpl? labelNode,
    bool isContinue,
  ) {
    if (labelNode == null) {
      return implicitLabelScope.getTarget(isContinue);
    } else {
      var labelScope = _labelScope;
      if (labelScope == null) {
        // There are no labels in scope, so by definition the label is
        // undefined.
        diagnosticReporter.atNode(
          labelNode,
          CompileTimeErrorCode.LABEL_UNDEFINED,
          arguments: [labelNode.name],
        );
        return null;
      }
      var definingScope = labelScope.lookup(labelNode.name);
      if (definingScope == null) {
        // No definition of the given label name could be found in any
        // enclosing scope.
        diagnosticReporter.atNode(
          labelNode,
          CompileTimeErrorCode.LABEL_UNDEFINED,
          arguments: [labelNode.name],
        );
        return null;
      }
      // The target has been found.
      labelNode.element = definingScope.element;
      if (_enclosingClosure case var enclosingClosure?) {
        var labelFragment = definingScope.element.firstFragment;
        var labelContainer = labelFragment.enclosingFragment;
        if (!identical(labelContainer, enclosingClosure.firstFragment)) {
          diagnosticReporter.atNode(
            labelNode,
            CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE,
            arguments: [labelNode.name],
          );
        }
      }
      var node = definingScope.node;
      if (isContinue &&
          node is! DoStatement &&
          node is! ForStatement &&
          node is! SwitchMember &&
          node is! WhileStatement) {
        diagnosticReporter.atNode(
          parentNode,
          CompileTimeErrorCode.CONTINUE_LABEL_INVALID,
        );
      }
      return node;
    }
  }

  /// Visits a documentation comment with a [DocumentationCommentScope] that encloses the
  /// current [nameScope].
  void _visitDocumentationComment(CommentImpl? node) {
    if (node == null) return;

    Scope outerScope = nameScope;
    Scope docImportInnerScope = _docImportScope.innerScope;
    try {
      _docImportScope.innerScope = nameScope;
      nameScope = _docImportScope;

      node.nameScope = nameScope;
      node.accept(this);
    } finally {
      nameScope = outerScope;
      _docImportScope.innerScope = docImportInnerScope;
    }
  }

  void _visitIf(IfElementOrStatementImpl node) {
    node.expression.accept(this);

    var caseClause = node.caseClause;
    if (caseClause != null) {
      var guardedPattern = caseClause.guardedPattern;
      _withNameScope(() {
        caseClause.nameScope = nameScope;
        var variables = guardedPattern.variables;
        for (var variable in variables.values) {
          _define(variable);
        }
        guardedPattern.accept(this);
        node.ifTrue.accept(this);
      });
      node.ifFalse?.accept(this);
    } else {
      node.ifTrue.accept(this);
      node.ifFalse?.accept(this);
    }
  }

  /// Visits the given statement.
  ///
  /// This is used by [ResolverVisitor] to correctly visit the 'then' and 'else'
  /// statements of an 'if' statement.
  void _visitStatementInScope(Statement? node) {
    if (node is BlockImpl) {
      // Don't create a scope around a block because the block will create it's
      // own scope.
      visitBlock(node);
    } else if (node != null) {
      var outerNameScope = nameScope;
      try {
        nameScope = LocalScope(nameScope);
        node.accept(this);
      } finally {
        nameScope = outerNameScope;
      }
    }
  }

  void _withDeclaredLocals(
    AstNodeWithNameScopeMixin node,
    List<Statement> statements,
    void Function() f,
  ) {
    var outerScope = nameScope;
    try {
      var enclosedScope = LocalScope(nameScope);
      for (var statement in BlockScope.elementsInStatements(statements)) {
        if (!statement.isWildcardFunction) {
          enclosedScope.add(statement);
        }
      }

      nameScope = enclosedScope;
      node.nameScope = nameScope;

      f();
    } finally {
      nameScope = outerScope;
    }
  }

  /// Run [f] with the new name scope.
  void _withNameScope(void Function() f) {
    var current = nameScope;
    try {
      nameScope = LocalScope(current);
      f();
    } finally {
      nameScope = current;
    }
  }

  /// Return the [Scope] to use while resolving inside the [node].
  ///
  /// Not every node has the scope set, for example we set the scopes for
  /// blocks, but statements don't have separate scopes. The compilation unit
  /// has the library scope.
  static Scope? getNodeNameScope(AstNode node) =>
      node is AstNodeWithNameScopeMixin ? node.nameScope : null;
}

/// Tracker for whether a `switch` statement has `default` or is on an
/// enumeration, and all the enum constants are covered.
class SwitchExhaustiveness {
  /// If the switch is on an enumeration, the set of enum constants to cover.
  /// Otherwise `null`.
  final Set<FieldElement>? _enumConstants;

  /// If the switch is on an enumeration, is `true` if the null value is
  /// covered, because the switch expression type is non-nullable, or `null`
  /// was covered explicitly.
  bool _isNullEnumValueCovered = false;

  bool isExhaustive = false;

  factory SwitchExhaustiveness(TypeImpl expressionType) {
    if (expressionType is InterfaceType) {
      var enum_ = expressionType.element3;
      if (enum_ is EnumElementImpl) {
        return SwitchExhaustiveness._(
          enum_.constants2.toSet(),
          expressionType.nullabilitySuffix == NullabilitySuffix.none,
        );
      }
    }
    return SwitchExhaustiveness._(null, false);
  }

  SwitchExhaustiveness._(this._enumConstants, this._isNullEnumValueCovered);

  void visitSwitchExpressionCase(SwitchExpressionCaseImpl node) {
    if (_enumConstants != null) {
      ExpressionImpl? caseConstant;
      var guardedPattern = node.guardedPattern;
      if (guardedPattern.whenClause == null) {
        var pattern = guardedPattern.pattern.unParenthesized;
        if (pattern is ConstantPatternImpl) {
          caseConstant = pattern.expression;
        }
      }
      _handleCaseConstant(caseConstant);
    }
  }

  void visitSwitchMember(SwitchStatementCaseGroup group) {
    for (var node in group.members) {
      if (_enumConstants != null) {
        ExpressionImpl? caseConstant;
        if (node is SwitchCaseImpl) {
          caseConstant = node.expression;
        } else if (node is SwitchPatternCaseImpl) {
          var guardedPattern = node.guardedPattern;
          if (guardedPattern.whenClause == null) {
            var pattern = guardedPattern.pattern.unParenthesized;
            if (pattern is ConstantPatternImpl) {
              caseConstant = pattern.expression;
            }
          }
        }
        _handleCaseConstant(caseConstant);
      } else if (node is SwitchDefault) {
        isExhaustive = true;
      }
    }
  }

  void _handleCaseConstant(ExpressionImpl? caseConstant) {
    if (caseConstant != null) {
      var element = _referencedElement(caseConstant);
      if (element is PropertyAccessorElement) {
        _enumConstants!.remove(element.variable3);
      }
      if (caseConstant is NullLiteral) {
        _isNullEnumValueCovered = true;
      }
      if (_enumConstants!.isEmpty && _isNullEnumValueCovered) {
        isExhaustive = true;
      }
    }
  }

  static Element? _referencedElement(Expression expression) {
    if (expression is ParenthesizedExpression) {
      return _referencedElement(expression.expression);
    } else if (expression is PrefixedIdentifier) {
      return expression.element;
    } else if (expression is PropertyAccess) {
      return expression.propertyName.element;
    } else if (expression is SimpleIdentifier) {
      return expression.element;
    }
    return null;
  }
}

class _WhyNotPromotedVisitor
    implements
        NonPromotionReasonVisitor<
          List<DiagnosticMessage>,
          AstNode,
          PromotableElement
        > {
  final Source source;

  final SyntacticEntity _errorEntity;

  final FlowAnalysisDataForTesting? _dataForTesting;

  PropertyAccessorElement? propertyReference;

  _WhyNotPromotedVisitor(this.source, this._errorEntity, this._dataForTesting);

  @override
  List<DiagnosticMessage> visitDemoteViaExplicitWrite(
    DemoteViaExplicitWrite<PromotableElement> reason,
  ) {
    var node = reason.node as AstNode;
    if (node is ForEachPartsWithIdentifier) {
      node = node.identifier;
    }
    if (_dataForTesting != null) {
      _dataForTesting.nonPromotionReasonTargets[node] = reason.shortName;
    }
    var variableName = reason.variable.name3;
    return [_contextMessageForWrite(variableName, node, reason)];
  }

  @override
  List<DiagnosticMessage> visitPropertyNotPromotedForInherentReason(
    PropertyNotPromotedForInherentReason reason,
  ) {
    var receiverElement = reason.propertyMember;
    if (receiverElement is PropertyAccessorElement) {
      var property = propertyReference = receiverElement;
      var propertyName = reason.propertyName;
      String message = switch (reason.whyNotPromotable) {
        shared.PropertyNonPromotabilityReason.isNotField =>
          "'$propertyName' refers to a getter so it couldn't be promoted.",
        shared.PropertyNonPromotabilityReason.isNotPrivate =>
          "'$propertyName' refers to a public property so it couldn't be "
              "promoted.",
        shared.PropertyNonPromotabilityReason.isExternal =>
          "'$propertyName' refers to an external field so it couldn't be "
              "promoted.",
        shared.PropertyNonPromotabilityReason.isNotFinal =>
          "'$propertyName' refers to a non-final field so it couldn't be "
              "promoted.",
      };
      return [
        DiagnosticMessageImpl(
          filePath: property.firstFragment.libraryFragment.source.fullName,
          message: message,
          offset: property.nonSynthetic.firstFragment.nameOffset2!,
          length: property.name3!.length,
          url: reason.documentationLink.url,
        ),
        if (!reason.fieldPromotionEnabled)
          _fieldPromotionUnavailableMessage(property, propertyName),
      ];
    } else {
      assert(
        receiverElement == null,
        'Unrecognized property element: ${receiverElement.runtimeType}',
      );
      return [];
    }
  }

  @override
  List<DiagnosticMessage> visitPropertyNotPromotedForNonInherentReason(
    PropertyNotPromotedForNonInherentReason reason,
  ) {
    var receiverElement = reason.propertyMember;
    if (receiverElement is PropertyAccessorElement) {
      var property = propertyReference = receiverElement;
      var propertyName = reason.propertyName;
      var library = receiverElement.library2 as LibraryElementImpl;
      var fieldNonPromotabilityInfo = library.fieldNameNonPromotabilityInfo;
      var fieldNameInfo = fieldNonPromotabilityInfo[reason.propertyName];
      var messages = <DiagnosticMessage>[];
      void addConflictMessage({
        required Element conflictingElement,
        required String kind,
        required Element enclosingElement,
        required NonPromotionDocumentationLink link,
      }) {
        var enclosingKindName = enclosingElement.kind.displayName;
        var enclosingName = enclosingElement.name3;
        var message =
            "'$propertyName' couldn't be promoted because there is a "
            "conflicting $kind in $enclosingKindName '$enclosingName'";
        var nonSyntheticElement = conflictingElement.nonSynthetic;
        var nonSyntheticFragment = nonSyntheticElement.firstFragment;
        var source = nonSyntheticFragment.libraryFragment?.source;
        messages.add(
          DiagnosticMessageImpl(
            filePath: source!.fullName,
            message: message,
            offset: nonSyntheticFragment.nameOffset2!,
            length: nonSyntheticElement.name3!.length,
            url: link.url,
          ),
        );
      }

      if (fieldNameInfo != null) {
        for (var field in fieldNameInfo.conflictingFields) {
          addConflictMessage(
            conflictingElement: field,
            kind: 'non-promotable field',
            enclosingElement: field.enclosingElement,
            link: NonPromotionDocumentationLink.conflictingNonPromotableField,
          );
        }
        for (var getter in fieldNameInfo.conflictingGetters) {
          addConflictMessage(
            conflictingElement: getter,
            kind: 'getter',
            enclosingElement: getter.enclosingElement,
            link: NonPromotionDocumentationLink.conflictingGetter,
          );
        }
        for (var nsmClass in fieldNameInfo.conflictingNsmClasses) {
          addConflictMessage(
            conflictingElement: nsmClass,
            kind: 'noSuchMethod forwarder',
            enclosingElement: nsmClass,
            link:
                NonPromotionDocumentationLink.conflictingNoSuchMethodForwarder,
          );
        }
      }
      if (reason.fieldPromotionEnabled) {
        // The only possible non-inherent reasons for field promotion to fail
        // are because of conflicts and because field promotion is disabled. So
        // if field promotion is enabled, the loops above should have found a
        // conflict.
        assert(messages.isNotEmpty);
      } else {
        messages.add(_fieldPromotionUnavailableMessage(property, propertyName));
      }
      return messages;
    } else {
      assert(
        receiverElement == null,
        'Unrecognized property element: ${receiverElement.runtimeType}',
      );
      return [];
    }
  }

  @override
  List<DiagnosticMessage> visitThisNotPromoted(ThisNotPromoted reason) {
    return [
      DiagnosticMessageImpl(
        filePath: source.fullName,
        message: "'this' can't be promoted",
        offset: _errorEntity.offset,
        length: _errorEntity.length,
        url: reason.documentationLink.url,
      ),
    ];
  }

  DiagnosticMessageImpl _contextMessageForWrite(
    String? variableName,
    AstNode node,
    DemoteViaExplicitWrite<PromotableElement> reason,
  ) {
    return DiagnosticMessageImpl(
      filePath: source.fullName,
      message:
          "Variable '${variableName!}' could not be promoted due to an "
          "assignment",
      offset: node.offset,
      length: node.length,
      url: reason.documentationLink.url,
    );
  }

  DiagnosticMessageImpl _fieldPromotionUnavailableMessage(
    PropertyAccessorElement property,
    String propertyName,
  ) {
    return DiagnosticMessageImpl(
      filePath: property.firstFragment.libraryFragment.source.fullName,
      message:
          "'$propertyName' couldn't be promoted "
          "because field promotion is only available in Dart 3.2 and "
          "above.",
      offset: property.nonSynthetic.firstFragment.nameOffset2!,
      length: property.name3!.length,
      url: NonPromotionDocumentationLink.fieldPromotionUnavailable.url,
    );
  }
}

extension on Element {
  bool get isWildcardFunction =>
      this is LocalFunctionElement &&
      name3 == '_' &&
      library2.hasWildcardVariablesFeatureEnabled;
}
