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

// @dart = 2.9

import 'dart:core' hide MapEntry;
import 'dart:core' as core;

import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';

import 'package:_fe_analyzer_shared/src/testing/id.dart';
import 'package:_fe_analyzer_shared/src/util/link.dart';
import 'package:front_end/src/fasta/kernel/class_hierarchy_builder.dart';

import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:kernel/type_algebra.dart';
import 'package:kernel/type_environment.dart';
import 'package:kernel/src/bounds_checks.dart' show calculateBounds;
import 'package:kernel/src/future_value_type.dart';
import 'package:kernel/src/legacy_erasure.dart';

import '../../base/instrumentation.dart'
    show
        Instrumentation,
        InstrumentationValueForMember,
        InstrumentationValueForType,
        InstrumentationValueForTypeArgs;

import '../../base/nnbd_mode.dart';

import '../../testing/id_extractor.dart';
import '../../testing/id_testing_utils.dart';

import '../builder/constructor_builder.dart';
import '../builder/extension_builder.dart';
import '../builder/member_builder.dart';

import '../fasta_codes.dart';

import '../kernel/class_hierarchy_builder.dart' show ClassMember;
import '../kernel/inference_visitor.dart';
import '../kernel/internal_ast.dart';
import '../kernel/invalid_type.dart';
import '../kernel/type_algorithms.dart' show hasAnyTypeVariables;

import '../names.dart';

import '../problems.dart' show internalProblem, unexpected, unhandled;

import '../source/source_library_builder.dart' show SourceLibraryBuilder;

import 'inference_helper.dart' show InferenceHelper;
import 'type_constraint_gatherer.dart' show TypeConstraintGatherer;
import 'type_demotion.dart';
import 'type_inference_engine.dart';
import 'type_schema.dart' show isKnown, UnknownType;
import 'type_schema_elimination.dart' show greatestClosure;
import 'type_schema_environment.dart'
    show
        getNamedParameterType,
        getPositionalParameterType,
        TypeConstraint,
        TypeVariableEliminator,
        TypeSchemaEnvironment;

part 'closure_context.dart';

/// Given a [FunctionNode], gets the named parameter identified by [name], or
/// `null` if there is no parameter with the given name.
VariableDeclaration getNamedFormal(FunctionNode function, String name) {
  for (VariableDeclaration formal in function.namedParameters) {
    if (formal.name == name) return formal;
  }
  return null;
}

/// Given a [FunctionNode], gets the [i]th positional formal parameter, or
/// `null` if there is no parameter with that index.
VariableDeclaration getPositionalFormal(FunctionNode function, int i) {
  if (i < function.positionalParameters.length) {
    return function.positionalParameters[i];
  } else {
    return null;
  }
}

bool isOverloadableArithmeticOperator(String name) {
  return identical(name, '+') ||
      identical(name, '-') ||
      identical(name, '*') ||
      identical(name, '%');
}

/// Enum denoting the kinds of contravariance check that might need to be
/// inserted for a method call.
enum MethodContravarianceCheckKind {
  /// No contravariance check is needed.
  none,

  /// The return value from the method call needs to be checked.
  checkMethodReturn,

  /// The method call needs to be desugared into a getter call, followed by an
  /// "as" check, followed by an invocation of the resulting function object.
  checkGetterReturn,
}

/// Keeps track of the local state for the type inference that occurs during
/// compilation of a single method body or top level initializer.
///
/// This class describes the interface for use by clients of type inference
/// (e.g. BodyBuilder).  Derived classes should derive from [TypeInferrerImpl].
abstract class TypeInferrer {
  SourceLibraryBuilder get library;

  /// Gets the [TypeSchemaEnvironment] being used for type inference.
  TypeSchemaEnvironment get typeSchemaEnvironment;

  /// Returns the [FlowAnalysis] used during inference.
  FlowAnalysis<TreeNode, Statement, Expression, VariableDeclaration, DartType>
      get flowAnalysis;

  /// The URI of the code for which type inference is currently being
  /// performed--this is used for testing.
  Uri get uriForInstrumentation;

  AssignedVariables<TreeNode, VariableDeclaration> get assignedVariables;

  /// Performs full type inference on the given field initializer.
  Expression inferFieldInitializer(
      InferenceHelper helper, DartType declaredType, Expression initializer);

  /// Performs type inference on the given function body.
  InferredFunctionBody inferFunctionBody(InferenceHelper helper, int fileOffset,
      DartType returnType, AsyncMarker asyncMarker, Statement body);

  /// Performs type inference on the given constructor initializer.
  void inferInitializer(InferenceHelper helper, Initializer initializer);

  /// Performs type inference on the given metadata annotations.
  void inferMetadata(
      InferenceHelper helper, TreeNode parent, List<Expression> annotations);

  /// Performs type inference on the given metadata annotations keeping the
  /// existing helper if possible.
  void inferMetadataKeepingHelper(
      TreeNode parent, List<Expression> annotations);

  /// Performs type inference on the given function parameter initializer
  /// expression.
  Expression inferParameterInitializer(
      InferenceHelper helper,
      Expression initializer,
      DartType declaredType,
      bool hasDeclaredInitializer);

  /// Ensures that all parameter types of [constructor] have been inferred.
  // TODO(johnniwinther): We are still parameters on synthesized mixin
  //  application constructors.
  void inferConstructorParameterTypes(Constructor constructor);
}

/// Concrete implementation of [TypeInferrer] specialized to work with kernel
/// objects.
class TypeInferrerImpl implements TypeInferrer {
  /// Marker object to indicate that a function takes an unknown number
  /// of arguments.
  final FunctionType unknownFunction;

  final TypeInferenceEngine engine;

  final FlowAnalysis<TreeNode, Statement, Expression, VariableDeclaration,
      DartType> flowAnalysis;

  final AssignedVariables<TreeNode, VariableDeclaration> assignedVariables;

  final InferenceDataForTesting dataForTesting;

  @override
  final Uri uriForInstrumentation;

  /// Indicates whether the construct we are currently performing inference for
  /// is outside of a method body, and hence top level type inference rules
  /// should apply.
  final bool isTopLevel;

  final ClassHierarchy classHierarchy;

  final Instrumentation instrumentation;

  final TypeSchemaEnvironment typeSchemaEnvironment;

  final InterfaceType thisType;

  @override
  final SourceLibraryBuilder library;

  InferenceHelper helper;

  /// Context information for the current closure, or `null` if we are not
  /// inside a closure.
  ClosureContext closureContext;

  TypeInferrerImpl(this.engine, this.uriForInstrumentation, bool topLevel,
      this.thisType, this.library, this.assignedVariables, this.dataForTesting)
      : assert(library != null),
        unknownFunction = new FunctionType(
            const [], const DynamicType(), library.nonNullable),
        classHierarchy = engine.classHierarchy,
        instrumentation = topLevel ? null : engine.instrumentation,
        typeSchemaEnvironment = engine.typeSchemaEnvironment,
        isTopLevel = topLevel,
        flowAnalysis = library.isNonNullableByDefault
            ? new FlowAnalysis(
                new TypeOperationsCfe(engine.typeSchemaEnvironment),
                assignedVariables)
            : new FlowAnalysis.legacy(
                new TypeOperationsCfe(engine.typeSchemaEnvironment),
                assignedVariables);

  CoreTypes get coreTypes => engine.coreTypes;

  bool get isNonNullableByDefault => library.isNonNullableByDefault;

  NnbdMode get nnbdMode => library.loader.nnbdMode;

  bool get useNewMethodInvocationEncoding =>
      library.loader.target.backendTarget.supportsNewMethodInvocationEncoding;

  DartType get bottomType =>
      isNonNullableByDefault ? const NeverType.nonNullable() : const NullType();

  DartType computeGreatestClosure(DartType type) {
    return greatestClosure(type, const DynamicType(), bottomType);
  }

  DartType computeGreatestClosure2(DartType type) {
    return greatestClosure(
        type,
        isNonNullableByDefault
            ? coreTypes.objectNullableRawType
            : const DynamicType(),
        bottomType);
  }

  DartType computeNullable(DartType type) {
    if (type is NullType || type is NeverType) {
      return const NullType();
    }
    return type.withDeclaredNullability(library.nullable);
  }

  Expression createReachabilityError(
      int fileOffset, Message errorMessage, Message warningMessage) {
    if (library.loader.target.context.options.warnOnReachabilityCheck &&
        warningMessage != null) {
      helper?.addProblem(warningMessage, fileOffset, noLength);
    }
    Arguments arguments;
    if (errorMessage != null) {
      arguments = new Arguments(
          [new StringLiteral(errorMessage.message)..fileOffset = fileOffset])
        ..fileOffset = fileOffset;
    } else {
      arguments = new Arguments([])..fileOffset = fileOffset;
    }
    assert(coreTypes.reachabilityErrorConstructor != null);
    return new Throw(
        new ConstructorInvocation(
            coreTypes.reachabilityErrorConstructor, arguments)
          ..fileOffset = fileOffset)
      ..fileOffset = fileOffset;
  }

  /// Computes a list of context messages explaining why [receiver] was not
  /// promoted, to be used when reporting an error for a larger expression
  /// containing [receiver].  [node] is the containing tree node.
  List<LocatedMessage> getWhyNotPromotedContext(
      Map<DartType, NonPromotionReason> whyNotPromoted,
      TreeNode node,
      bool Function(DartType) typeFilter) {
    List<LocatedMessage> context;
    if (whyNotPromoted != null && whyNotPromoted.isNotEmpty) {
      _WhyNotPromotedVisitor whyNotPromotedVisitor =
          new _WhyNotPromotedVisitor(this);
      for (core.MapEntry<DartType, NonPromotionReason> entry
          in whyNotPromoted.entries) {
        if (!typeFilter(entry.key)) continue;
        LocatedMessage message = entry.value.accept(whyNotPromotedVisitor);
        if (dataForTesting != null) {
          String nonPromotionReasonText = entry.value.shortName;
          List<String> args = <String>[];
          if (whyNotPromotedVisitor.propertyReference != null) {
            Id id = computeMemberId(whyNotPromotedVisitor.propertyReference);
            args.add('target: $id');
          }
          if (whyNotPromotedVisitor.propertyType != null) {
            String typeText = typeToText(whyNotPromotedVisitor.propertyType,
                TypeRepresentation.analyzerNonNullableByDefault);
            args.add('type: $typeText');
          }
          if (args.isNotEmpty) {
            nonPromotionReasonText += '(${args.join(', ')})';
          }
          TreeNode origNode = node;
          while (origNode is VariableGet &&
              origNode.variable.name == null &&
              origNode.variable.initializer != null) {
            // This is a read of a synthetic variable, presumably from a "let".
            // Find the original expression.
            // TODO(johnniwinther): add a general solution for getting the
            // original node for testing.
            origNode = (origNode as VariableGet).variable.initializer;
          }
          dataForTesting.flowAnalysisResult.nonPromotionReasons[origNode] =
              nonPromotionReasonText;
        }
        // Note: this will always pick the first viable reason (only).  I
        // (paulberry) believe this is the one that will be the most relevant,
        // but I need to do more testing to validate that.  I can't do that
        // additional testing yet because at the moment we only handle failed
        // promotions to non-nullable.
        // TODO(paulberry): do more testing and then expand on the comment
        // above.
        context = [message];
        break;
      }
    }
    return context;
  }

  /// Returns `true` if exceptions should be thrown in paths reachable only due
  /// to unsoundness in flow analysis in mixed mode.
  bool get shouldThrowUnsoundnessException =>
      isNonNullableByDefault && nnbdMode != NnbdMode.Strong;

  void registerIfUnreachableForTesting(TreeNode node, {bool isReachable}) {
    if (dataForTesting == null) return;
    isReachable ??= flowAnalysis.isReachable;
    if (!isReachable) {
      dataForTesting.flowAnalysisResult.unreachableNodes.add(node);
    }
  }

  @override
  void inferConstructorParameterTypes(Constructor target) {
    ConstructorBuilder constructor = engine.beingInferred[target];
    if (constructor != null) {
      // There is a cyclic dependency where inferring the types of the
      // initializing formals of a constructor required us to infer the
      // corresponding field type which required us to know the type of the
      // constructor.
      String name = target.enclosingClass.name;
      if (target.name.text.isNotEmpty) {
        // TODO(ahe): Use `inferrer.helper.constructorNameForDiagnostics`
        // instead. However, `inferrer.helper` may be null.
        name += ".${target.name.text}";
      }
      constructor.library.addProblem(
          templateCantInferTypeDueToCircularity.withArguments(name),
          target.fileOffset,
          name.length,
          target.fileUri);
      for (VariableDeclaration declaration
          in target.function.positionalParameters) {
        declaration.type ??= const InvalidType();
      }
      for (VariableDeclaration declaration in target.function.namedParameters) {
        declaration.type ??= const InvalidType();
      }
    } else if ((constructor = engine.toBeInferred[target]) != null) {
      engine.toBeInferred.remove(target);
      engine.beingInferred[target] = constructor;
      constructor.inferFormalTypes();
      engine.beingInferred.remove(target);
    }
  }

  @override
  void inferInitializer(InferenceHelper helper, Initializer initializer) {
    this.helper = helper;
    // Use polymorphic dispatch on [KernelInitializer] to perform whatever
    // kind of type inference is correct for this kind of initializer.
    // TODO(paulberry): experiment to see if dynamic dispatch would be better,
    // so that the type hierarchy will be simpler (which may speed up "is"
    // checks).
    if (initializer is InitializerJudgment) {
      initializer.acceptInference(new InferenceVisitor(this));
    } else {
      initializer.accept(new InferenceVisitor(this));
    }
    this.helper = null;
  }

  bool isDoubleContext(DartType typeContext) {
    // A context is a double context if double is assignable to it but int is
    // not.  That is the type context is a double context if it is:
    //   * double
    //   * FutureOr<T> where T is a double context
    //
    // We check directly, rather than using isAssignable because it's simpler.
    while (typeContext is FutureOrType) {
      FutureOrType type = typeContext;
      typeContext = type.typeArgument;
    }
    return typeContext is InterfaceType &&
        typeContext.classNode == coreTypes.doubleClass;
  }

  bool isAssignable(DartType contextType, DartType expressionType) {
    if (isNonNullableByDefault) {
      if (expressionType is DynamicType) return true;
      return typeSchemaEnvironment
          .performNullabilityAwareSubtypeCheck(expressionType, contextType)
          .isSubtypeWhenUsingNullabilities();
    }
    return typeSchemaEnvironment
        .performNullabilityAwareSubtypeCheck(expressionType, contextType)
        .orSubtypeCheckFor(contextType, expressionType, typeSchemaEnvironment)
        .isSubtypeWhenIgnoringNullabilities();
  }

  Expression ensureAssignableResult(
      DartType expectedType, ExpressionInferenceResult result,
      {int fileOffset,
      bool isVoidAllowed: false,
      Template<Message Function(DartType, DartType, bool)> errorTemplate,
      Template<Message Function(DartType, DartType, bool)>
          nullabilityErrorTemplate,
      Template<Message Function(DartType, bool)> nullabilityNullErrorTemplate,
      Template<Message Function(DartType, DartType, bool)>
          nullabilityNullTypeErrorTemplate,
      Template<Message Function(DartType, DartType, DartType, DartType, bool)>
          nullabilityPartErrorTemplate}) {
    return ensureAssignable(
        expectedType, result.inferredType, result.expression,
        fileOffset: fileOffset,
        isVoidAllowed: isVoidAllowed,
        errorTemplate: errorTemplate,
        nullabilityErrorTemplate: nullabilityErrorTemplate,
        nullabilityNullErrorTemplate: nullabilityNullErrorTemplate,
        nullabilityNullTypeErrorTemplate: nullabilityNullTypeErrorTemplate,
        nullabilityPartErrorTemplate: nullabilityPartErrorTemplate);
  }

  /// Ensures that [expressionType] is assignable to [contextType].
  ///
  /// Checks whether [expressionType] can be assigned to the greatest closure of
  /// [contextType], and inserts an implicit downcast, inserts a tear-off, or
  /// reports an error if appropriate.
  ///
  /// If [declaredContextType] is provided, this is used instead of
  /// [contextType] for reporting the type against which [expressionType] isn't
  /// assignable. This is used when checking the assignability of return
  /// statements in async functions in which the assignability is checked
  /// against the future value type but the reporting should refer to the
  /// declared return type.
  ///
  /// If [runtimeCheckedType] is provided, this is used for the implicit cast,
  /// otherwise [contextType] is used. This is used for return from async
  /// where the returned expression is wrapped in a `Future`, if necessary,
  /// before returned and therefore shouldn't be checked to be a `Future`
  /// directly.
  Expression ensureAssignable(
      DartType contextType, DartType expressionType, Expression expression,
      {int fileOffset,
      DartType declaredContextType,
      DartType runtimeCheckedType,
      bool isVoidAllowed: false,
      Template<Message Function(DartType, DartType, bool)> errorTemplate,
      Template<Message Function(DartType, DartType, bool)>
          nullabilityErrorTemplate,
      Template<Message Function(DartType, bool)> nullabilityNullErrorTemplate,
      Template<Message Function(DartType, DartType, bool)>
          nullabilityNullTypeErrorTemplate,
      Template<Message Function(DartType, DartType, DartType, DartType, bool)>
          nullabilityPartErrorTemplate,
      Map<DartType, NonPromotionReason> Function() whyNotPromoted}) {
    assert(contextType != null);

    // [errorTemplate], [nullabilityErrorTemplate], and
    // [nullabilityPartErrorTemplate] should be provided together.
    assert((errorTemplate == null) == (nullabilityErrorTemplate == null) &&
        (nullabilityErrorTemplate == null) ==
            (nullabilityPartErrorTemplate == null));
    // [nullabilityNullErrorTemplate] and [nullabilityNullTypeErrorTemplate]
    // should be provided together.
    assert((nullabilityNullErrorTemplate == null) ==
        (nullabilityNullTypeErrorTemplate == null));
    errorTemplate ??= templateInvalidAssignmentError;
    if (nullabilityErrorTemplate == null) {
      // Use [templateInvalidAssignmentErrorNullabilityNull] only if no
      // specific [nullabilityErrorTemplate] template was passed.
      nullabilityNullErrorTemplate ??=
          templateInvalidAssignmentErrorNullabilityNull;
    }
    nullabilityNullTypeErrorTemplate ??= nullabilityErrorTemplate ??
        templateInvalidAssignmentErrorNullabilityNullType;
    nullabilityErrorTemplate ??= templateInvalidAssignmentErrorNullability;
    nullabilityPartErrorTemplate ??=
        templateInvalidAssignmentErrorPartNullability;

    // We don't need to insert assignability checks when doing top level type
    // inference since top level type inference only cares about the type that
    // is inferred (the kernel code is discarded).
    if (isTopLevel) return expression;

    fileOffset ??= expression.fileOffset;
    contextType = computeGreatestClosure(contextType);

    DartType initialContextType = runtimeCheckedType ?? contextType;

    Template<Message Function(DartType, DartType, bool)>
        preciseTypeErrorTemplate = _getPreciseTypeErrorTemplate(expression);
    AssignabilityResult assignabilityResult = _computeAssignabilityKind(
        contextType, expressionType,
        isNonNullableByDefault: isNonNullableByDefault,
        isVoidAllowed: isVoidAllowed,
        isExpressionTypePrecise: preciseTypeErrorTemplate != null);

    Expression result;
    switch (assignabilityResult.kind) {
      case AssignabilityKind.assignable:
        result = expression;
        break;
      case AssignabilityKind.assignableCast:
        // Insert an implicit downcast.
        result = new AsExpression(expression, initialContextType)
          ..isTypeError = true
          ..isForNonNullableByDefault = isNonNullableByDefault
          ..isForDynamic = expressionType is DynamicType
          ..fileOffset = fileOffset;
        break;
      case AssignabilityKind.assignableTearoff:
        result = _tearOffCall(expression, expressionType, fileOffset).tearoff;
        break;
      case AssignabilityKind.assignableTearoffCast:
        result = new AsExpression(
            _tearOffCall(expression, expressionType, fileOffset).tearoff,
            initialContextType)
          ..isTypeError = true
          ..isForNonNullableByDefault = isNonNullableByDefault
          ..fileOffset = fileOffset;
        break;
      case AssignabilityKind.unassignable:
        // Error: not assignable.  Perform error recovery.
        result = _wrapUnassignableExpression(
            expression,
            expressionType,
            contextType,
            errorTemplate.withArguments(expressionType,
                declaredContextType ?? contextType, isNonNullableByDefault));

        break;
      case AssignabilityKind.unassignableVoid:
        // Error: not assignable.  Perform error recovery.
        result = helper.wrapInProblem(
            expression, messageVoidExpression, expression.fileOffset, noLength);
        break;
      case AssignabilityKind.unassignablePrecise:
        // The type of the expression is known precisely, so an implicit
        // downcast is guaranteed to fail.  Insert a compile-time error.
        result = helper.wrapInProblem(
            expression,
            preciseTypeErrorTemplate.withArguments(
                expressionType, contextType, isNonNullableByDefault),
            expression.fileOffset,
            noLength);
        break;
      case AssignabilityKind.unassignableTearoff:
        TypedTearoff typedTearoff =
            _tearOffCall(expression, expressionType, fileOffset);
        result = _wrapUnassignableExpression(
            typedTearoff.tearoff,
            typedTearoff.tearoffType,
            contextType,
            errorTemplate.withArguments(typedTearoff.tearoffType,
                declaredContextType ?? contextType, isNonNullableByDefault));

        break;
      case AssignabilityKind.unassignableCantTearoff:
        result = _wrapTearoffErrorExpression(
            expression, contextType, templateNullableTearoffError);
        break;
      case AssignabilityKind.unassignableNullability:
        if (expressionType == assignabilityResult.subtype &&
            contextType == assignabilityResult.supertype) {
          if (expression is NullLiteral &&
              nullabilityNullErrorTemplate != null) {
            result = _wrapUnassignableExpression(
                expression,
                expressionType,
                contextType,
                nullabilityNullErrorTemplate.withArguments(
                    declaredContextType ?? contextType,
                    isNonNullableByDefault));
          } else if (expressionType is NullType) {
            result = _wrapUnassignableExpression(
                expression,
                expressionType,
                contextType,
                nullabilityNullTypeErrorTemplate.withArguments(
                    expressionType,
                    declaredContextType ?? contextType,
                    isNonNullableByDefault));
          } else {
            whyNotPromoted ??= flowAnalysis?.whyNotPromoted(expression);
            result = _wrapUnassignableExpression(
                expression,
                expressionType,
                contextType,
                nullabilityErrorTemplate.withArguments(expressionType,
                    declaredContextType ?? contextType, isNonNullableByDefault),
                context: getWhyNotPromotedContext(
                    whyNotPromoted?.call(),
                    expression,
                    (type) => typeSchemaEnvironment.isSubtypeOf(type,
                        contextType, SubtypeCheckMode.withNullabilities)));
          }
        } else {
          result = _wrapUnassignableExpression(
              expression,
              expressionType,
              contextType,
              nullabilityPartErrorTemplate.withArguments(
                  expressionType,
                  declaredContextType ?? contextType,
                  assignabilityResult.subtype,
                  assignabilityResult.supertype,
                  isNonNullableByDefault));
        }
        break;
      case AssignabilityKind.unassignableNullabilityTearoff:
        TypedTearoff typedTearoff =
            _tearOffCall(expression, expressionType, fileOffset);
        if (expressionType == assignabilityResult.subtype &&
            contextType == assignabilityResult.supertype) {
          result = _wrapUnassignableExpression(
              typedTearoff.tearoff,
              typedTearoff.tearoffType,
              contextType,
              nullabilityErrorTemplate.withArguments(typedTearoff.tearoffType,
                  declaredContextType ?? contextType, isNonNullableByDefault));
        } else {
          result = _wrapUnassignableExpression(
              typedTearoff.tearoff,
              typedTearoff.tearoffType,
              contextType,
              nullabilityPartErrorTemplate.withArguments(
                  typedTearoff.tearoffType,
                  declaredContextType ?? contextType,
                  assignabilityResult.subtype,
                  assignabilityResult.supertype,
                  isNonNullableByDefault));
        }
        break;
      default:
        return unhandled("${assignabilityResult}", "ensureAssignable",
            fileOffset, helper.uri);
    }

    if (!identical(result, expression)) {
      flowAnalysis?.forwardExpression(result, expression);
    }
    return result;
  }

  Expression _wrapTearoffErrorExpression(Expression expression,
      DartType contextType, Template<Message Function(String)> template) {
    assert(template != null);
    Expression errorNode = new AsExpression(
        expression,
        // TODO(ahe): The outline phase doesn't correctly remove invalid
        // uses of type variables, for example, on static members. Once
        // that has been fixed, we should always be able to use
        // [contextType] directly here.
        hasAnyTypeVariables(contextType)
            ? const NeverType.nonNullable()
            : contextType)
      ..isTypeError = true
      ..fileOffset = expression.fileOffset;
    if (contextType is! InvalidType) {
      errorNode = helper.wrapInProblem(
          errorNode,
          template.withArguments(callName.text),
          errorNode.fileOffset,
          noLength);
    }
    return errorNode;
  }

  Expression _wrapUnassignableExpression(Expression expression,
      DartType expressionType, DartType contextType, Message message,
      {List<LocatedMessage> context}) {
    Expression errorNode = new AsExpression(
        expression,
        // TODO(ahe): The outline phase doesn't correctly remove invalid
        // uses of type variables, for example, on static members. Once
        // that has been fixed, we should always be able to use
        // [contextType] directly here.
        hasAnyTypeVariables(contextType)
            ? const NeverType.nonNullable()
            : contextType)
      ..isTypeError = true
      ..isForNonNullableByDefault = isNonNullableByDefault
      ..fileOffset = expression.fileOffset;
    if (contextType is! InvalidType && expressionType is! InvalidType) {
      errorNode = helper.wrapInProblem(
          errorNode, message, errorNode.fileOffset, noLength,
          context: context);
    }
    return errorNode;
  }

  TypedTearoff _tearOffCall(
      Expression expression, InterfaceType expressionType, int fileOffset) {
    Class classNode = expressionType.classNode;
    Member callMember = classHierarchy.getInterfaceMember(classNode, callName);
    assert(callMember is Procedure && callMember.kind == ProcedureKind.Method);

    // Replace expression with:
    // `let t = expression in t == null ? null : t.call`
    VariableDeclaration t =
        new VariableDeclaration.forValue(expression, type: expressionType)
          ..fileOffset = fileOffset;
    Expression nullCheck;
    // TODO(johnniwinther): Avoid null-check for non-nullable expressions.
    if (useNewMethodInvocationEncoding) {
      nullCheck = new EqualsNull(new VariableGet(t)..fileOffset = fileOffset)
        ..fileOffset = fileOffset;
    } else {
      nullCheck = new MethodInvocation(
          new VariableGet(t)..fileOffset = fileOffset,
          equalsName,
          new Arguments(
              <Expression>[new NullLiteral()..fileOffset = fileOffset]))
        ..fileOffset = fileOffset;
    }
    PropertyGet tearOff =
        new PropertyGet(new VariableGet(t), callName, callMember)
          ..fileOffset = fileOffset;
    DartType tearoffType =
        getGetterTypeForMemberTarget(callMember, expressionType)
            .withDeclaredNullability(expressionType.nullability);
    ConditionalExpression conditional = new ConditionalExpression(nullCheck,
        new NullLiteral()..fileOffset = fileOffset, tearOff, tearoffType);
    return new TypedTearoff(
        tearoffType, new Let(t, conditional)..fileOffset = fileOffset);
  }

  /// Computes the assignability kind of [expressionType] to [contextType].
  ///
  /// The computation is side-effect free.
  AssignabilityResult _computeAssignabilityKind(
      DartType contextType, DartType expressionType,
      {bool isNonNullableByDefault,
      bool isVoidAllowed,
      bool isExpressionTypePrecise}) {
    assert(isNonNullableByDefault != null);
    assert(isVoidAllowed != null);
    assert(isExpressionTypePrecise != null);

    // If an interface type is being assigned to a function type, see if we
    // should tear off `.call`.
    // TODO(paulberry): use resolveTypeParameter.  See findInterfaceMember.
    bool needsTearoff = false;
    if (expressionType is InterfaceType) {
      Class classNode = (expressionType as InterfaceType).classNode;
      Member callMember =
          classHierarchy.getInterfaceMember(classNode, callName);
      if (callMember is Procedure && callMember.kind == ProcedureKind.Method) {
        if (_shouldTearOffCall(contextType, expressionType)) {
          needsTearoff = true;
          if (isNonNullableByDefault && expressionType.isPotentiallyNullable) {
            return const AssignabilityResult(
                AssignabilityKind.unassignableCantTearoff);
          }
          expressionType =
              getGetterTypeForMemberTarget(callMember, expressionType)
                  .withDeclaredNullability(expressionType.nullability);
        }
      }
    }

    if (expressionType is VoidType && !isVoidAllowed) {
      return const AssignabilityResult(AssignabilityKind.unassignableVoid);
    }

    IsSubtypeOf isDirectSubtypeResult = typeSchemaEnvironment
        .performNullabilityAwareSubtypeCheck(expressionType, contextType);
    bool isDirectlyAssignable = isNonNullableByDefault
        ? isDirectSubtypeResult.isSubtypeWhenUsingNullabilities()
        : isDirectSubtypeResult.isSubtypeWhenIgnoringNullabilities();
    if (isDirectlyAssignable) {
      return needsTearoff
          ? const AssignabilityResult(AssignabilityKind.assignableTearoff)
          : const AssignabilityResult(AssignabilityKind.assignable);
    }

    bool isIndirectlyAssignable = isNonNullableByDefault
        ? expressionType is DynamicType
        : typeSchemaEnvironment
            .performNullabilityAwareSubtypeCheck(contextType, expressionType)
            .isSubtypeWhenIgnoringNullabilities();
    if (!isIndirectlyAssignable) {
      if (isNonNullableByDefault &&
          isDirectSubtypeResult.isSubtypeWhenIgnoringNullabilities()) {
        return needsTearoff
            ? new AssignabilityResult.withTypes(
                AssignabilityKind.unassignableNullabilityTearoff,
                isDirectSubtypeResult.subtype,
                isDirectSubtypeResult.supertype)
            : new AssignabilityResult.withTypes(
                AssignabilityKind.unassignableNullability,
                isDirectSubtypeResult.subtype,
                isDirectSubtypeResult.supertype);
      } else {
        return needsTearoff
            ? const AssignabilityResult(AssignabilityKind.unassignableTearoff)
            : const AssignabilityResult(AssignabilityKind.unassignable);
      }
    }
    if (isExpressionTypePrecise) {
      // The type of the expression is known precisely, so an implicit
      // downcast is guaranteed to fail.  Insert a compile-time error.
      return const AssignabilityResult(AssignabilityKind.unassignablePrecise);
    }
    // Insert an implicit downcast.
    return needsTearoff
        ? const AssignabilityResult(AssignabilityKind.assignableTearoffCast)
        : const AssignabilityResult(AssignabilityKind.assignableCast);
  }

  bool isNull(DartType type) {
    return type is NullType;
  }

  /// Computes the type arguments for an access to an extension instance member
  /// on [extension] with the static [receiverType]. If [explicitTypeArguments]
  /// are provided, these are returned, otherwise type arguments are inferred
  /// using [receiverType].
  List<DartType> computeExtensionTypeArgument(Extension extension,
      List<DartType> explicitTypeArguments, DartType receiverType) {
    if (explicitTypeArguments != null) {
      assert(explicitTypeArguments.length == extension.typeParameters.length);
      return explicitTypeArguments;
    } else if (extension.typeParameters.isEmpty) {
      assert(explicitTypeArguments == null);
      return const <DartType>[];
    } else {
      return inferExtensionTypeArguments(extension, receiverType);
    }
  }

  /// Infers the type arguments for an access to an extension instance member
  /// on [extension] with the static [receiverType].
  List<DartType> inferExtensionTypeArguments(
      Extension extension, DartType receiverType) {
    List<TypeParameter> typeParameters = extension.typeParameters;
    DartType onType = extension.onType;
    List<DartType> inferredTypes =
        new List<DartType>.filled(typeParameters.length, const UnknownType());
    typeSchemaEnvironment.inferGenericFunctionOrType(null, typeParameters,
        [onType], [receiverType], null, inferredTypes, library.library);
    return inferredTypes;
  }

  /// Returns extension member declared immediately for [receiverType].
  ///
  /// If none is found, [defaultTarget] is returned.
  ObjectAccessTarget _findDirectExtensionMember(
      ExtensionType receiverType, Name name, int fileOffset,
      {ObjectAccessTarget defaultTarget}) {
    Member targetMember;
    Member targetTearoff;
    ProcedureKind targetKind;
    for (ExtensionMemberDescriptor descriptor
        in receiverType.extension.members) {
      if (descriptor.name == name) {
        switch (descriptor.kind) {
          case ExtensionMemberKind.Method:
            targetMember = descriptor.member.asMember;
            targetTearoff ??= targetMember;
            targetKind = ProcedureKind.Method;
            break;
          case ExtensionMemberKind.TearOff:
            targetTearoff = descriptor.member.asMember;
            break;
          case ExtensionMemberKind.Getter:
            targetMember = descriptor.member.asMember;
            targetTearoff = null;
            targetKind = ProcedureKind.Getter;
            break;
          case ExtensionMemberKind.Setter:
            targetMember = descriptor.member.asMember;
            targetTearoff = null;
            targetKind = ProcedureKind.Setter;
            break;
          case ExtensionMemberKind.Operator:
            targetMember = descriptor.member.asMember;
            targetTearoff = null;
            targetKind = ProcedureKind.Operator;
            break;
          default:
            unhandled("${descriptor.kind}", "_findDirectExtensionMember",
                fileOffset, library.fileUri);
        }
      }
    }
    if (targetMember != null) {
      assert(targetKind != null);
      return new ObjectAccessTarget.extensionMember(
          targetMember, targetTearoff, targetKind, receiverType.typeArguments);
    } else {
      return defaultTarget;
    }
  }

  /// Returns the extension member access by the given [name] for a receiver
  /// with the static [receiverType].
  ///
  /// If none is found, [defaultTarget] is returned.
  ///
  /// If multiple are found, none more specific, an
  /// [AmbiguousExtensionAccessTarget] is returned. This access kind results in
  /// a compile-time error, but is used to provide a better message than just
  /// reporting that the receiver does not have a member by the given name.
  ///
  /// If [isPotentiallyNullableAccess] is `true`, the returned extension member
  /// is flagged as a nullable extension member access. This access kind results
  /// in a compile-time error, but is used to provide a better message than just
  /// reporting that the receiver does not have a member by the given name.
  ObjectAccessTarget _findExtensionMember(
      DartType receiverType, Class classNode, Name name, int fileOffset,
      {bool setter: false,
      ObjectAccessTarget defaultTarget,
      bool isPotentiallyNullableAccess: false}) {
    Name otherName = name;
    bool otherIsSetter;
    if (name == indexGetName) {
      // [] must be checked against []=.
      otherName = indexSetName;
      otherIsSetter = false;
    } else if (name == indexSetName) {
      // []= must be checked against [].
      otherName = indexGetName;
      otherIsSetter = false;
    } else {
      otherName = name;
      otherIsSetter = !setter;
    }

    Member otherMember =
        _getInterfaceMember(classNode, otherName, otherIsSetter, fileOffset);
    if (otherMember != null) {
      // If we're looking for `foo` and `foo=` can be found or vice-versa then
      // extension methods should not be found.
      return defaultTarget;
    }

    ExtensionAccessCandidate bestSoFar;
    List<ExtensionAccessCandidate> noneMoreSpecific = [];
    library.forEachExtensionInScope((ExtensionBuilder extensionBuilder) {
      MemberBuilder thisBuilder =
          extensionBuilder.lookupLocalMemberByName(name, setter: setter);
      MemberBuilder otherBuilder = extensionBuilder
          .lookupLocalMemberByName(otherName, setter: otherIsSetter);
      if ((thisBuilder != null && !thisBuilder.isStatic) ||
          (otherBuilder != null && !otherBuilder.isStatic)) {
        DartType onType;
        DartType onTypeInstantiateToBounds;
        List<DartType> inferredTypeArguments;
        if (extensionBuilder.extension.typeParameters.isEmpty) {
          onTypeInstantiateToBounds =
              onType = extensionBuilder.extension.onType;
          inferredTypeArguments = const <DartType>[];
        } else {
          List<TypeParameter> typeParameters =
              extensionBuilder.extension.typeParameters;
          inferredTypeArguments = inferExtensionTypeArguments(
              extensionBuilder.extension, receiverType);
          Substitution inferredSubstitution =
              Substitution.fromPairs(typeParameters, inferredTypeArguments);

          for (int index = 0; index < typeParameters.length; index++) {
            TypeParameter typeParameter = typeParameters[index];
            DartType typeArgument = inferredTypeArguments[index];
            DartType bound =
                inferredSubstitution.substituteType(typeParameter.bound);
            if (!typeSchemaEnvironment.isSubtypeOf(
                typeArgument, bound, SubtypeCheckMode.withNullabilities)) {
              return;
            }
          }
          onType = inferredSubstitution
              .substituteType(extensionBuilder.extension.onType);
          List<DartType> instantiateToBoundTypeArguments = calculateBounds(
              typeParameters, coreTypes.objectClass, library.library);
          Substitution instantiateToBoundsSubstitution = Substitution.fromPairs(
              typeParameters, instantiateToBoundTypeArguments);
          onTypeInstantiateToBounds = instantiateToBoundsSubstitution
              .substituteType(extensionBuilder.extension.onType);
        }

        if (typeSchemaEnvironment.isSubtypeOf(
            receiverType, onType, SubtypeCheckMode.withNullabilities)) {
          ExtensionAccessCandidate candidate = new ExtensionAccessCandidate(
              thisBuilder ?? otherBuilder,
              onType,
              onTypeInstantiateToBounds,
              thisBuilder != null &&
                      !thisBuilder.isField &&
                      !thisBuilder.isStatic
                  ? new ObjectAccessTarget.extensionMember(
                      setter
                          ? thisBuilder.writeTarget
                          : thisBuilder.invokeTarget,
                      thisBuilder.readTarget,
                      thisBuilder.kind,
                      inferredTypeArguments,
                      isPotentiallyNullable: isPotentiallyNullableAccess)
                  : const ObjectAccessTarget.missing(),
              isPlatform: extensionBuilder.library.importUri.scheme == 'dart');
          if (noneMoreSpecific.isNotEmpty) {
            bool isMostSpecific = true;
            for (ExtensionAccessCandidate other in noneMoreSpecific) {
              bool isMoreSpecific =
                  candidate.isMoreSpecificThan(typeSchemaEnvironment, other);
              if (isMoreSpecific != true) {
                isMostSpecific = false;
                break;
              }
            }
            if (isMostSpecific) {
              bestSoFar = candidate;
              noneMoreSpecific.clear();
            } else {
              noneMoreSpecific.add(candidate);
            }
          } else if (bestSoFar == null) {
            bestSoFar = candidate;
          } else {
            bool isMoreSpecific =
                candidate.isMoreSpecificThan(typeSchemaEnvironment, bestSoFar);
            if (isMoreSpecific == true) {
              bestSoFar = candidate;
            } else if (isMoreSpecific == null) {
              noneMoreSpecific.add(bestSoFar);
              noneMoreSpecific.add(candidate);
              bestSoFar = null;
            }
          }
        }
      }
    });
    if (bestSoFar != null) {
      return bestSoFar.target;
    } else {
      if (noneMoreSpecific.isNotEmpty) {
        return new AmbiguousExtensionAccessTarget(noneMoreSpecific);
      }
    }
    return defaultTarget;
  }

  /// Finds a member of [receiverType] called [name], and if it is found,
  /// reports it through instrumentation using [fileOffset].
  ///
  /// For the case where [receiverType] is a [FunctionType], and the name
  /// is `call`, the string 'call' is returned as a sentinel object.
  ///
  /// For the case where [receiverType] is `dynamic`, and the name is declared
  /// in Object, the member from Object is returned though the call may not end
  /// up targeting it if the arguments do not match (the basic principle is that
  /// the Object member is used for inferring types only if noSuchMethod cannot
  /// be targeted due to, e.g., an incorrect argument count).
  ObjectAccessTarget findInterfaceMember(
      DartType receiverType, Name name, int fileOffset,
      {bool setter: false,
      bool instrumented: true,
      bool includeExtensionMethods: false}) {
    assert(receiverType != null && isKnown(receiverType));

    DartType receiverBound = resolveTypeParameter(receiverType);

    bool isReceiverTypePotentiallyNullable = isNonNullableByDefault &&
        receiverType.isPotentiallyNullable &&
        // Calls to `==` are always on a non-null receiver.
        name != equalsName;

    Class classNode = receiverBound is InterfaceType
        ? receiverBound.classNode
        : coreTypes.objectClass;

    if (isReceiverTypePotentiallyNullable) {
      Member member =
          _getInterfaceMember(coreTypes.objectClass, name, setter, fileOffset);
      if (member != null) {
        // Null implements all Object members so this is not considered a
        // potentially nullable access.
        return new ObjectAccessTarget.objectMember(member);
      }
      if (includeExtensionMethods && receiverBound is! DynamicType) {
        ObjectAccessTarget target = _findExtensionMember(
            isNonNullableByDefault ? receiverType : receiverBound,
            coreTypes.objectClass,
            name,
            fileOffset,
            setter: setter);
        if (target != null) {
          return target;
        }
      }
    }

    if (receiverBound is FunctionType && name == callName) {
      return isReceiverTypePotentiallyNullable
          ? const ObjectAccessTarget.nullableCallFunction()
          : const ObjectAccessTarget.callFunction();
    } else if (receiverBound is NeverType) {
      switch (receiverBound.nullability) {
        case Nullability.nonNullable:
          return const ObjectAccessTarget.never();
        case Nullability.nullable:
        case Nullability.legacy:
          // Never? and Never* are equivalent to Null.
          return findInterfaceMember(const NullType(), name, fileOffset);
        case Nullability.undetermined:
          return internalProblem(
              templateInternalProblemUnsupportedNullability.withArguments(
                  "${receiverBound.nullability}",
                  receiverBound,
                  isNonNullableByDefault),
              fileOffset,
              library.fileUri);
      }
    }

    ObjectAccessTarget target;
    Member interfaceMember =
        _getInterfaceMember(classNode, name, setter, fileOffset);
    if (interfaceMember != null) {
      target = new ObjectAccessTarget.interfaceMember(interfaceMember,
          isPotentiallyNullable: isReceiverTypePotentiallyNullable);
    } else if (receiverBound is DynamicType) {
      target = const ObjectAccessTarget.dynamic();
    } else if (receiverBound is InvalidType) {
      target = const ObjectAccessTarget.invalid();
    } else if (receiverBound is InterfaceType &&
        receiverBound.classNode == coreTypes.functionClass &&
        name == callName) {
      target = isReceiverTypePotentiallyNullable
          ? const ObjectAccessTarget.nullableCallFunction()
          : const ObjectAccessTarget.callFunction();
    } else if (library.enableExtensionTypesInLibrary &&
        receiverBound is ExtensionType) {
      target = _findDirectExtensionMember(receiverBound, name, fileOffset,
          defaultTarget: const ObjectAccessTarget.missing());
    } else {
      target = const ObjectAccessTarget.missing();
    }
    if (instrumented &&
        receiverBound != const DynamicType() &&
        (target.isInstanceMember || target.isObjectMember)) {
      instrumentation?.record(uriForInstrumentation, fileOffset, 'target',
          new InstrumentationValueForMember(target.member));
    }

    if (target.isMissing && includeExtensionMethods) {
      if (isReceiverTypePotentiallyNullable) {
        // When the receiver type is potentially nullable we would have found
        // the extension member above, if available. Therefore we know that we
        // are in an erroneous case and instead look up the extension member on
        // the non-nullable receiver bound but flag the found target as a
        // nullable extension member access. This is done to provide the better
        // error message that the extension member exists but that the access is
        // invalid.
        target = _findExtensionMember(
            isNonNullableByDefault
                ? receiverType.toNonNull()
                : receiverBound.toNonNull(),
            classNode,
            name,
            fileOffset,
            setter: setter,
            defaultTarget: target,
            isPotentiallyNullableAccess: true);
      } else {
        target = _findExtensionMember(
            isNonNullableByDefault ? receiverType : receiverBound,
            classNode,
            name,
            fileOffset,
            setter: setter,
            defaultTarget: target);
      }
    }
    return target;
  }

  /// If target is missing on a non-dynamic receiver, an error is reported
  /// using [errorTemplate] and an invalid expression is returned.
  Expression reportMissingInterfaceMember(
      ObjectAccessTarget target,
      DartType receiverType,
      Name name,
      int fileOffset,
      Template<Message Function(String, DartType, bool)> errorTemplate) {
    assert(receiverType != null && isKnown(receiverType));
    if (!isTopLevel && target.isMissing && errorTemplate != null) {
      int length = name.text.length;
      if (identical(name.text, callName.text) ||
          identical(name.text, unaryMinusName.text)) {
        length = 1;
      }
      return helper.buildProblem(
          errorTemplate.withArguments(name.text,
              resolveTypeParameter(receiverType), isNonNullableByDefault),
          fileOffset,
          length);
    }
    return null;
  }

  /// Returns [type] as passed from [superClass] to the current class.
  ///
  /// If a legacy class occurs between the current class and [superClass] then
  /// [type] needs to be legacy erased. For instance
  ///
  ///    // Opt in:
  ///    class Super {
  ///      int extendedMethod(int i, {required int j}) => i;
  ///    }
  ///    class Mixin {
  ///      int mixedInMethod(int i, {required int j}) => i;
  ///    }
  ///    // Opt out:
  ///    class Legacy extends Super with Mixin {}
  ///    // Opt in:
  ///    class Class extends Legacy {
  ///      test() {
  ///        // Ok to call `Legacy.extendedMethod` since its type is
  ///        // `int* Function(int*, {int* j})`.
  ///        super.extendedMethod(null);
  ///        // Ok to call `Legacy.mixedInMethod` since its type is
  ///        // `int* Function(int*, {int* j})`.
  ///        super.mixedInMethod(null);
  ///      }
  ///    }
  ///
  DartType computeTypeFromSuperClass(Class superClass, DartType type) {
    if (needsLegacyErasure(thisType.classNode, superClass)) {
      type = legacyErasure(type);
    }
    return type;
  }

  /// Returns the type of [target] when accessed as a getter on [receiverType].
  ///
  /// For instance
  ///
  ///    class Class<T> {
  ///      T method() {}
  ///      T getter => null;
  ///    }
  ///
  ///    Class<int> c = ...
  ///    c.method; // The getter type is `int Function()`.
  ///    c.getter; // The getter type is `int`.
  ///
  DartType getGetterType(ObjectAccessTarget target, DartType receiverType) {
    switch (target.kind) {
      case ObjectAccessTargetKind.callFunction:
      case ObjectAccessTargetKind.nullableCallFunction:
        return receiverType;
      case ObjectAccessTargetKind.invalid:
        return const InvalidType();
      case ObjectAccessTargetKind.dynamic:
      case ObjectAccessTargetKind.missing:
      case ObjectAccessTargetKind.ambiguous:
        return const DynamicType();
      case ObjectAccessTargetKind.never:
        return const NeverType.nonNullable();
      case ObjectAccessTargetKind.instanceMember:
      case ObjectAccessTargetKind.objectMember:
      case ObjectAccessTargetKind.nullableInstanceMember:
        return getGetterTypeForMemberTarget(target.member, receiverType);
      case ObjectAccessTargetKind.extensionMember:
      case ObjectAccessTargetKind.nullableExtensionMember:
        switch (target.extensionMethodKind) {
          case ProcedureKind.Method:
          case ProcedureKind.Operator:
            FunctionType functionType =
                target.member.function.computeFunctionType(library.nonNullable);
            List<TypeParameter> extensionTypeParameters = functionType
                .typeParameters
                .take(target.inferredExtensionTypeArguments.length)
                .toList();
            Substitution substitution = Substitution.fromPairs(
                extensionTypeParameters, target.inferredExtensionTypeArguments);
            DartType resultType = substitution.substituteType(new FunctionType(
                functionType.positionalParameters.skip(1).toList(),
                functionType.returnType,
                library.nonNullable,
                namedParameters: functionType.namedParameters,
                typeParameters: functionType.typeParameters
                    .skip(target.inferredExtensionTypeArguments.length)
                    .toList(),
                requiredParameterCount:
                    functionType.requiredParameterCount - 1));
            if (!isNonNullableByDefault) {
              resultType = legacyErasure(resultType);
            }
            return resultType;
          case ProcedureKind.Getter:
            FunctionType functionType =
                target.member.function.computeFunctionType(library.nonNullable);
            List<TypeParameter> extensionTypeParameters = functionType
                .typeParameters
                .take(target.inferredExtensionTypeArguments.length)
                .toList();
            Substitution substitution = Substitution.fromPairs(
                extensionTypeParameters, target.inferredExtensionTypeArguments);
            DartType resultType =
                substitution.substituteType(functionType.returnType);
            if (!isNonNullableByDefault) {
              resultType = legacyErasure(resultType);
            }
            return resultType;
          case ProcedureKind.Setter:
          case ProcedureKind.Factory:
            break;
        }
    }
    throw unhandled('$target', 'getGetterType', null, null);
  }

  /// Returns the getter type of [interfaceMember] on a receiver of type
  /// [receiverType].
  ///
  /// For instance
  ///
  ///    class Class<T> {
  ///      T method() {}
  ///      T getter => null;
  ///    }
  ///
  ///    Class<int> c = ...
  ///    c.method; // The getter type is `int Function()`.
  ///    c.getter; // The getter type is `int`.
  ///
  DartType getGetterTypeForMemberTarget(
      Member interfaceMember, DartType receiverType) {
    Class memberClass = interfaceMember.enclosingClass;
    assert(interfaceMember is Field || interfaceMember is Procedure,
        "Unexpected interface member $interfaceMember.");
    DartType calleeType = interfaceMember.getterType;
    if (memberClass.typeParameters.isNotEmpty) {
      receiverType = resolveTypeParameter(receiverType);
      if (receiverType is InterfaceType) {
        List<DartType> castedTypeArguments = classHierarchy
            .getTypeArgumentsAsInstanceOf(receiverType, memberClass);
        calleeType = Substitution.fromPairs(
                memberClass.typeParameters, castedTypeArguments)
            .substituteType(calleeType);
      }
    }
    if (!isNonNullableByDefault) {
      calleeType = legacyErasure(calleeType);
    }
    return calleeType;
  }

  /// Returns the type of [target] when accessed as an invocation on
  /// [receiverType].
  ///
  /// If the target is known not to be invokable [unknownFunction] is returned.
  ///
  /// For instance
  ///
  ///    class Class<T> {
  ///      T method() {}
  ///      T Function() getter1 => null;
  ///      T getter2 => null;
  ///    }
  ///
  ///    Class<int> c = ...
  ///    c.method; // The getter type is `int Function()`.
  ///    c.getter1; // The getter type is `int Function()`.
  ///    c.getter2; // The getter type is [unknownFunction].
  ///
  FunctionType getFunctionType(
      ObjectAccessTarget target, DartType receiverType) {
    switch (target.kind) {
      case ObjectAccessTargetKind.callFunction:
      case ObjectAccessTargetKind.nullableCallFunction:
        return _getFunctionType(receiverType);
      case ObjectAccessTargetKind.dynamic:
      case ObjectAccessTargetKind.never:
      case ObjectAccessTargetKind.invalid:
      case ObjectAccessTargetKind.missing:
      case ObjectAccessTargetKind.ambiguous:
        return unknownFunction;
      case ObjectAccessTargetKind.instanceMember:
      case ObjectAccessTargetKind.objectMember:
      case ObjectAccessTargetKind.nullableInstanceMember:
        return _getFunctionType(
            getGetterTypeForMemberTarget(target.member, receiverType));
      case ObjectAccessTargetKind.extensionMember:
      case ObjectAccessTargetKind.nullableExtensionMember:
        switch (target.extensionMethodKind) {
          case ProcedureKind.Method:
          case ProcedureKind.Operator:
            FunctionType functionType =
                target.member.function.computeFunctionType(library.nonNullable);
            if (!isNonNullableByDefault) {
              functionType = legacyErasure(functionType);
            }
            return functionType;
          case ProcedureKind.Getter:
            // TODO(johnniwinther): Handle implicit .call on extension getter.
            return _getFunctionType(target.member.function.returnType);
          case ProcedureKind.Setter:
          case ProcedureKind.Factory:
            break;
        }
    }
    throw unhandled('$target', 'getFunctionType', null, null);
  }

  /// Returns the type of the receiver argument in an access to an extension
  /// member on [extension] with the given extension [typeArguments].
  DartType getExtensionReceiverType(
      Extension extension, List<DartType> typeArguments) {
    DartType receiverType = extension.onType;
    if (extension.typeParameters.isNotEmpty) {
      Substitution substitution =
          Substitution.fromPairs(extension.typeParameters, typeArguments);
      return substitution.substituteType(receiverType);
    }
    return receiverType;
  }

  /// Returns the return type of the invocation of [target] on [receiverType].
  // TODO(johnniwinther): Cleanup [getFunctionType], [getReturnType],
  // [getIndexKeyType] and [getIndexSetValueType]. We shouldn't need that many.
  DartType getReturnType(ObjectAccessTarget target, DartType receiverType) {
    switch (target.kind) {
      case ObjectAccessTargetKind.instanceMember:
      case ObjectAccessTargetKind.objectMember:
      case ObjectAccessTargetKind.nullableInstanceMember:
        FunctionType functionType = _getFunctionType(
            getGetterTypeForMemberTarget(target.member, receiverType));
        return functionType.returnType;
        break;
      case ObjectAccessTargetKind.extensionMember:
      case ObjectAccessTargetKind.nullableExtensionMember:
        switch (target.extensionMethodKind) {
          case ProcedureKind.Operator:
            FunctionType functionType =
                target.member.function.computeFunctionType(library.nonNullable);
            DartType returnType = functionType.returnType;
            if (functionType.typeParameters.isNotEmpty) {
              Substitution substitution = Substitution.fromPairs(
                  functionType.typeParameters,
                  target.inferredExtensionTypeArguments);
              returnType = substitution.substituteType(returnType);
            }
            if (!isNonNullableByDefault) {
              returnType = legacyErasure(returnType);
            }
            return returnType;
          default:
            throw unhandled('$target', 'getFunctionType', null, null);
        }
        break;
      case ObjectAccessTargetKind.never:
        return const NeverType.nonNullable();
      case ObjectAccessTargetKind.invalid:
        return const InvalidType();
      case ObjectAccessTargetKind.callFunction:
      case ObjectAccessTargetKind.nullableCallFunction:
      case ObjectAccessTargetKind.dynamic:
      case ObjectAccessTargetKind.missing:
      case ObjectAccessTargetKind.ambiguous:
        break;
    }
    return const DynamicType();
  }

  DartType getPositionalParameterTypeForTarget(
      ObjectAccessTarget target, DartType receiverType, int index) {
    switch (target.kind) {
      case ObjectAccessTargetKind.instanceMember:
      case ObjectAccessTargetKind.objectMember:
      case ObjectAccessTargetKind.nullableInstanceMember:
        FunctionType functionType = _getFunctionType(
            getGetterTypeForMemberTarget(target.member, receiverType));
        if (functionType.positionalParameters.length > index) {
          return functionType.positionalParameters[index];
        }
        break;
      case ObjectAccessTargetKind.extensionMember:
      case ObjectAccessTargetKind.nullableExtensionMember:
        FunctionType functionType =
            target.member.function.computeFunctionType(library.nonNullable);
        if (functionType.positionalParameters.length > index + 1) {
          DartType keyType = functionType.positionalParameters[index + 1];
          if (functionType.typeParameters.isNotEmpty) {
            Substitution substitution = Substitution.fromPairs(
                functionType.typeParameters,
                target.inferredExtensionTypeArguments);
            keyType = substitution.substituteType(keyType);
          }
          if (!isNonNullableByDefault) {
            keyType = legacyErasure(keyType);
          }
          return keyType;
        }
        break;
      case ObjectAccessTargetKind.invalid:
        return const InvalidType();
      case ObjectAccessTargetKind.callFunction:
      case ObjectAccessTargetKind.nullableCallFunction:
      case ObjectAccessTargetKind.dynamic:
      case ObjectAccessTargetKind.never:
      case ObjectAccessTargetKind.missing:
      case ObjectAccessTargetKind.ambiguous:
        break;
    }
    return const DynamicType();
  }

  /// Returns the type of the 'key' parameter in an [] or []= implementation.
  ///
  /// For instance
  ///
  ///    class Class<K, V> {
  ///      V operator [](K key) => null;
  ///      void operator []=(K key, V value) {}
  ///    }
  ///
  ///    extension Extension<K, V> on Class<K, V> {
  ///      V operator [](K key) => null;
  ///      void operator []=(K key, V value) {}
  ///    }
  ///
  ///    new Class<int, String>()[0];             // The key type is `int`.
  ///    new Class<int, String>()[0] = 'foo';     // The key type is `int`.
  ///    Extension<int, String>(null)[0];         // The key type is `int`.
  ///    Extension<int, String>(null)[0] = 'foo'; // The key type is `int`.
  ///
  DartType getIndexKeyType(ObjectAccessTarget target, DartType receiverType) {
    switch (target.kind) {
      case ObjectAccessTargetKind.instanceMember:
      case ObjectAccessTargetKind.objectMember:
      case ObjectAccessTargetKind.nullableInstanceMember:
        FunctionType functionType = _getFunctionType(
            getGetterTypeForMemberTarget(target.member, receiverType));
        if (functionType.positionalParameters.length >= 1) {
          return functionType.positionalParameters[0];
        }
        break;
      case ObjectAccessTargetKind.extensionMember:
      case ObjectAccessTargetKind.nullableExtensionMember:
        switch (target.extensionMethodKind) {
          case ProcedureKind.Operator:
            FunctionType functionType =
                target.member.function.computeFunctionType(library.nonNullable);
            if (functionType.positionalParameters.length >= 2) {
              DartType keyType = functionType.positionalParameters[1];
              if (functionType.typeParameters.isNotEmpty) {
                Substitution substitution = Substitution.fromPairs(
                    functionType.typeParameters,
                    target.inferredExtensionTypeArguments);
                keyType = substitution.substituteType(keyType);
              }
              if (!isNonNullableByDefault) {
                keyType = legacyErasure(keyType);
              }
              return keyType;
            }
            break;
          default:
            throw unhandled('$target', 'getFunctionType', null, null);
        }
        break;
      case ObjectAccessTargetKind.invalid:
        return const InvalidType();
      case ObjectAccessTargetKind.callFunction:
      case ObjectAccessTargetKind.nullableCallFunction:
      case ObjectAccessTargetKind.dynamic:
      case ObjectAccessTargetKind.never:
      case ObjectAccessTargetKind.missing:
      case ObjectAccessTargetKind.ambiguous:
        break;
    }
    return const DynamicType();
  }

  /// Returns the type of the 'value' parameter in an []= implementation.
  ///
  /// For instance
  ///
  ///    class Class<K, V> {
  ///      void operator []=(K key, V value) {}
  ///    }
  ///
  ///    extension Extension<K, V> on Class<K, V> {
  ///      void operator []=(K key, V value) {}
  ///    }
  ///
  ///    new Class<int, String>()[0] = 'foo';     // The value type is `String`.
  ///    Extension<int, String>(null)[0] = 'foo'; // The value type is `String`.
  ///
  DartType getIndexSetValueType(
      ObjectAccessTarget target, DartType receiverType) {
    switch (target.kind) {
      case ObjectAccessTargetKind.instanceMember:
      case ObjectAccessTargetKind.objectMember:
      case ObjectAccessTargetKind.nullableInstanceMember:
        FunctionType functionType = _getFunctionType(
            getGetterTypeForMemberTarget(target.member, receiverType));
        if (functionType.positionalParameters.length >= 2) {
          return functionType.positionalParameters[1];
        }
        break;
      case ObjectAccessTargetKind.extensionMember:
      case ObjectAccessTargetKind.nullableExtensionMember:
        switch (target.extensionMethodKind) {
          case ProcedureKind.Operator:
            FunctionType functionType =
                target.member.function.computeFunctionType(library.nonNullable);
            if (functionType.positionalParameters.length >= 3) {
              DartType indexType = functionType.positionalParameters[2];
              if (functionType.typeParameters.isNotEmpty) {
                Substitution substitution = Substitution.fromPairs(
                    functionType.typeParameters,
                    target.inferredExtensionTypeArguments);
                indexType = substitution.substituteType(indexType);
              }
              if (!isNonNullableByDefault) {
                indexType = legacyErasure(indexType);
              }
              return indexType;
            }
            break;
          default:
            throw unhandled('$target', 'getFunctionType', null, null);
        }
        break;
      case ObjectAccessTargetKind.invalid:
        return const InvalidType();
      case ObjectAccessTargetKind.callFunction:
      case ObjectAccessTargetKind.nullableCallFunction:
      case ObjectAccessTargetKind.dynamic:
      case ObjectAccessTargetKind.never:
      case ObjectAccessTargetKind.missing:
      case ObjectAccessTargetKind.ambiguous:
        break;
    }
    return const DynamicType();
  }

  FunctionType _getFunctionType(DartType calleeType) {
    calleeType = resolveTypeParameter(calleeType);
    if (calleeType is FunctionType) {
      if (!isNonNullableByDefault) {
        calleeType = legacyErasure(calleeType);
      }
      return calleeType;
    }
    return unknownFunction;
  }

  FunctionType getFunctionTypeForImplicitCall(DartType calleeType) {
    calleeType = resolveTypeParameter(calleeType);
    if (calleeType is FunctionType) {
      if (!isNonNullableByDefault) {
        calleeType = legacyErasure(calleeType);
      }
      return calleeType;
    } else if (calleeType is InterfaceType) {
      Member member =
          _getInterfaceMember(calleeType.classNode, callName, false, -1);
      if (member != null) {
        DartType callType = getGetterTypeForMemberTarget(member, calleeType);
        if (callType is FunctionType) {
          if (!isNonNullableByDefault) {
            callType = legacyErasure(callType);
          }
          return callType;
        }
      }
    }
    return unknownFunction;
  }

  DartType getDerivedTypeArgumentOf(DartType type, Class class_) {
    if (type is InterfaceType) {
      List<DartType> typeArgumentsAsInstanceOfClass =
          classHierarchy.getTypeArgumentsAsInstanceOf(type, class_);
      if (typeArgumentsAsInstanceOfClass != null) {
        return typeArgumentsAsInstanceOfClass[0];
      }
    }
    return null;
  }

  /// If the [member] is a forwarding stub, return the target it forwards to.
  /// Otherwise return the given [member].
  Member getRealTarget(Member member) {
    if (member is Procedure && member.isForwardingStub) {
      return member.abstractForwardingStubTarget;
    }
    return member;
  }

  DartType getSetterType(ObjectAccessTarget target, DartType receiverType) {
    switch (target.kind) {
      case ObjectAccessTargetKind.dynamic:
      case ObjectAccessTargetKind.never:
      case ObjectAccessTargetKind.missing:
      case ObjectAccessTargetKind.ambiguous:
        return const DynamicType();
      case ObjectAccessTargetKind.invalid:
        return const InvalidType();
      case ObjectAccessTargetKind.instanceMember:
      case ObjectAccessTargetKind.objectMember:
      case ObjectAccessTargetKind.nullableInstanceMember:
        Member interfaceMember = target.member;
        Class memberClass = interfaceMember.enclosingClass;
        DartType setterType;
        if (interfaceMember is Procedure) {
          assert(interfaceMember.kind == ProcedureKind.Setter);
          List<VariableDeclaration> setterParameters =
              interfaceMember.function.positionalParameters;
          setterType = setterParameters.length > 0
              ? setterParameters[0].type
              : const DynamicType();
        } else if (interfaceMember is Field) {
          setterType = interfaceMember.type;
        } else {
          throw unhandled(interfaceMember.runtimeType.toString(),
              'getSetterType', null, null);
        }
        if (memberClass.typeParameters.isNotEmpty) {
          receiverType = resolveTypeParameter(receiverType);
          if (receiverType is InterfaceType) {
            setterType = Substitution.fromPairs(
                    memberClass.typeParameters,
                    classHierarchy.getTypeArgumentsAsInstanceOf(
                        receiverType, memberClass))
                .substituteType(setterType);
          }
        }
        if (!isNonNullableByDefault) {
          setterType = legacyErasure(setterType);
        }
        return setterType;
      case ObjectAccessTargetKind.extensionMember:
      case ObjectAccessTargetKind.nullableExtensionMember:
        switch (target.extensionMethodKind) {
          case ProcedureKind.Setter:
            FunctionType functionType =
                target.member.function.computeFunctionType(library.nonNullable);
            List<TypeParameter> extensionTypeParameters = functionType
                .typeParameters
                .take(target.inferredExtensionTypeArguments.length)
                .toList();
            Substitution substitution = Substitution.fromPairs(
                extensionTypeParameters, target.inferredExtensionTypeArguments);
            DartType setterType = substitution
                .substituteType(functionType.positionalParameters[1]);
            if (!isNonNullableByDefault) {
              setterType = legacyErasure(setterType);
            }
            return setterType;
          case ProcedureKind.Method:
          case ProcedureKind.Getter:
          case ProcedureKind.Factory:
          case ProcedureKind.Operator:
            break;
        }
        // TODO(johnniwinther): Compute the right setter type.
        return const DynamicType();
      case ObjectAccessTargetKind.callFunction:
      case ObjectAccessTargetKind.nullableCallFunction:
        break;
    }
    throw unhandled(target.runtimeType.toString(), 'getSetterType', null, null);
  }

  DartType getTypeArgumentOf(DartType type, Class class_) {
    if (type is InterfaceType && identical(type.classNode, class_)) {
      return type.typeArguments[0];
    } else {
      return const UnknownType();
    }
  }

  /// Modifies a type as appropriate when inferring a declared variable's type.
  DartType inferDeclarationType(DartType initializerType,
      {bool forSyntheticVariable: false}) {
    if (initializerType == null) {
      assert(isTopLevel, "No initializer type provided.");
      return null;
    }
    if (initializerType is NullType) {
      // If the initializer type is Null or bottom, the inferred type is
      // dynamic.
      // TODO(paulberry): this rule is inherited from analyzer behavior but is
      // not spec'ed anywhere.
      return const DynamicType();
    }
    if (forSyntheticVariable) {
      return normalizeNullabilityInLibrary(initializerType, library.library);
    } else {
      return demoteTypeInLibrary(initializerType, library.library);
    }
  }

  void inferSyntheticVariable(VariableDeclarationImpl variable) {
    assert(variable.isImplicitlyTyped);
    assert(variable.initializer != null);
    ExpressionInferenceResult result = inferExpression(
        variable.initializer, const UnknownType(), true,
        isVoidAllowed: true);
    variable.initializer = result.expression..parent = variable;
    DartType inferredType =
        inferDeclarationType(result.inferredType, forSyntheticVariable: true);
    instrumentation?.record(uriForInstrumentation, variable.fileOffset, 'type',
        new InstrumentationValueForType(inferredType));
    variable.type = inferredType;
  }

  Link<NullAwareGuard> inferSyntheticVariableNullAware(
      VariableDeclarationImpl variable) {
    assert(variable.isImplicitlyTyped);
    assert(variable.initializer != null);
    ExpressionInferenceResult result = inferNullAwareExpression(
        variable.initializer, const UnknownType(), true,
        isVoidAllowed: true);

    Link<NullAwareGuard> nullAwareGuards = result.nullAwareGuards;
    variable.initializer = result.nullAwareAction..parent = variable;

    DartType inferredType =
        inferDeclarationType(result.inferredType, forSyntheticVariable: true);
    instrumentation?.record(uriForInstrumentation, variable.fileOffset, 'type',
        new InstrumentationValueForType(inferredType));
    variable.type = inferredType;
    return nullAwareGuards;
  }

  NullAwareGuard createNullAwareGuard(VariableDeclaration variable) {
    Member equalsMember =
        findInterfaceMember(variable.type, equalsName, variable.fileOffset)
            .member;
    // Ensure operator == member even for `Never`.
    equalsMember ??= findInterfaceMember(const DynamicType(), equalsName, -1,
            instrumented: false)
        .member;
    return new NullAwareGuard(
        variable, variable.fileOffset, equalsMember, this);
  }

  ExpressionInferenceResult wrapExpressionInferenceResultInProblem(
      ExpressionInferenceResult result,
      Message message,
      int fileOffset,
      int length,
      {List<LocatedMessage> context}) {
    return createNullAwareExpressionInferenceResult(
        result.inferredType,
        helper.wrapInProblem(
            result.nullAwareAction, message, fileOffset, length,
            context: context),
        result.nullAwareGuards);
  }

  ExpressionInferenceResult createNullAwareExpressionInferenceResult(
      DartType inferredType,
      Expression expression,
      Link<NullAwareGuard> nullAwareGuards) {
    if (nullAwareGuards != null && nullAwareGuards.isNotEmpty) {
      return new NullAwareExpressionInferenceResult(
          computeNullable(inferredType),
          inferredType,
          nullAwareGuards,
          expression);
    } else {
      return new ExpressionInferenceResult(inferredType, expression);
    }
  }

  /// Performs type inference on the given [expression].
  ///
  /// [typeContext] is the expected type of the expression, based on surrounding
  /// code.  [typeNeeded] indicates whether it is necessary to compute the
  /// actual type of the expression.  If [typeNeeded] is `true`,
  /// [ExpressionInferenceResult.inferredType] is the actual type of the
  /// expression; otherwise `null`.
  ///
  /// Derived classes should override this method with logic that dispatches on
  /// the expression type and calls the appropriate specialized "infer" method.
  ExpressionInferenceResult _inferExpression(
      Expression expression, DartType typeContext, bool typeNeeded,
      {bool isVoidAllowed: false, bool forEffect: false}) {
    registerIfUnreachableForTesting(expression);

    // `null` should never be used as the type context.  An instance of
    // `UnknownType` should be used instead.
    assert(typeContext != null);

    // For full (non-top level) inference, we need access to the
    // ExpressionGeneratorHelper so that we can perform error recovery.
    assert(isTopLevel || helper != null);

    // When doing top level inference, we skip subexpressions whose type isn't
    // needed so that we don't induce bogus dependencies on fields mentioned in
    // those subexpressions.
    if (!typeNeeded) return new ExpressionInferenceResult(null, expression);

    InferenceVisitor visitor = new InferenceVisitor(this);
    ExpressionInferenceResult result;
    if (expression is ExpressionJudgment) {
      result = expression.acceptInference(visitor, typeContext);
    } else if (expression is InternalExpression) {
      result = expression.acceptInference(visitor, typeContext);
    } else {
      result = expression.accept1(visitor, typeContext);
    }
    DartType inferredType = result.inferredType;
    assert(inferredType != null,
        "No type inferred for $expression (${expression.runtimeType}).");
    if (inferredType is VoidType && !isVoidAllowed) {
      if (expression.parent is! ArgumentsImpl) {
        helper?.addProblem(
            messageVoidExpression, expression.fileOffset, noLength);
      }
    }
    if (coreTypes.isBottom(result.inferredType)) {
      flowAnalysis.handleExit();
      if (shouldThrowUnsoundnessException &&
          // Don't throw on expressions that inherently return the bottom type.
          !(result.nullAwareAction is Throw ||
              result.nullAwareAction is Rethrow ||
              result.nullAwareAction is InvalidExpression)) {
        Expression replacement = createLet(
            createVariable(result.expression, result.inferredType),
            createReachabilityError(expression.fileOffset,
                messageNeverValueError, messageNeverValueWarning));
        flowAnalysis.forwardExpression(replacement, result.expression);
        result =
            new ExpressionInferenceResult(result.inferredType, replacement);
      }
    }
    return result;
  }

  ExpressionInferenceResult inferExpression(
      Expression expression, DartType typeContext, bool typeNeeded,
      {bool isVoidAllowed: false, bool forEffect: false}) {
    ExpressionInferenceResult result = _inferExpression(
        expression, typeContext, typeNeeded,
        isVoidAllowed: isVoidAllowed, forEffect: forEffect);
    return result.stopShorting();
  }

  ExpressionInferenceResult inferNullAwareExpression(
      Expression expression, DartType typeContext, bool typeNeeded,
      {bool isVoidAllowed: false, bool forEffect: false}) {
    ExpressionInferenceResult result = _inferExpression(
        expression, typeContext, typeNeeded,
        isVoidAllowed: isVoidAllowed, forEffect: forEffect);
    if (isNonNullableByDefault) {
      return result;
    } else {
      return result.stopShorting();
    }
  }

  @override
  Expression inferFieldInitializer(
    InferenceHelper helper,
    DartType context,
    Expression initializer,
  ) {
    assert(closureContext == null);
    assert(!isTopLevel);
    this.helper = helper;
    ExpressionInferenceResult initializerResult =
        inferExpression(initializer, context, true, isVoidAllowed: true);
    initializer = ensureAssignableResult(context, initializerResult,
        isVoidAllowed: context is VoidType);
    this.helper = null;
    return initializer;
  }

  @override
  InferredFunctionBody inferFunctionBody(InferenceHelper helper, int fileOffset,
      DartType returnType, AsyncMarker asyncMarker, Statement body) {
    assert(body != null);
    assert(closureContext == null);
    this.helper = helper;
    closureContext = new ClosureContext(this, asyncMarker, returnType, false);
    StatementInferenceResult result = inferStatement(body);
    if (dataForTesting != null) {
      if (!flowAnalysis.isReachable) {
        dataForTesting.flowAnalysisResult.functionBodiesThatDontComplete
            .add(body);
      }
    }
    result =
        closureContext.handleImplicitReturn(this, body, result, fileOffset);
    DartType futureValueType = closureContext.futureValueType;
    assert(
        !(isNonNullableByDefault &&
            asyncMarker == AsyncMarker.Async &&
            futureValueType == null),
        "No future value type computed.");
    closureContext = null;
    this.helper = null;
    flowAnalysis.finish();
    return new InferredFunctionBody(
        result.hasChanged ? result.statement : body, futureValueType);
  }

  InvocationInferenceResult inferInvocation(DartType typeContext, int offset,
      FunctionType calleeType, Arguments arguments,
      {List<VariableDeclaration> hoistedExpressions,
      bool isSpecialCasedBinaryOperator: false,
      bool isSpecialCasedTernaryOperator: false,
      DartType receiverType,
      bool skipTypeArgumentInference: false,
      bool isConst: false,
      bool isImplicitExtensionMember: false,
      bool isImplicitCall: false,
      Member staticTarget,
      bool isExtensionMemberInvocation = false}) {
    int extensionTypeParameterCount = getExtensionTypeParameterCount(arguments);
    if (extensionTypeParameterCount != 0) {
      return _inferGenericExtensionMethodInvocation(extensionTypeParameterCount,
          typeContext, offset, calleeType, arguments, hoistedExpressions,
          isSpecialCasedBinaryOperator: isSpecialCasedBinaryOperator,
          isSpecialCasedTernaryOperator: isSpecialCasedTernaryOperator,
          receiverType: receiverType,
          skipTypeArgumentInference: skipTypeArgumentInference,
          isConst: isConst,
          isImplicitExtensionMember: isImplicitExtensionMember);
    }
    return _inferInvocation(
        typeContext, offset, calleeType, arguments, hoistedExpressions,
        isSpecialCasedBinaryOperator: isSpecialCasedBinaryOperator,
        isSpecialCasedTernaryOperator: isSpecialCasedTernaryOperator,
        receiverType: receiverType,
        skipTypeArgumentInference: skipTypeArgumentInference,
        isConst: isConst,
        isImplicitExtensionMember: isImplicitExtensionMember,
        isImplicitCall: isImplicitCall,
        staticTarget: staticTarget,
        isExtensionMemberInvocation: isExtensionMemberInvocation);
  }

  InvocationInferenceResult _inferGenericExtensionMethodInvocation(
      int extensionTypeParameterCount,
      DartType typeContext,
      int offset,
      FunctionType calleeType,
      Arguments arguments,
      List<VariableDeclaration> hoistedExpressions,
      {bool isSpecialCasedBinaryOperator: false,
      bool isSpecialCasedTernaryOperator: false,
      DartType receiverType,
      bool skipTypeArgumentInference: false,
      bool isConst: false,
      bool isImplicitExtensionMember: false,
      bool isImplicitCall: false,
      Member staticTarget}) {
    FunctionType extensionFunctionType = new FunctionType(
        [calleeType.positionalParameters.first],
        const DynamicType(),
        library.nonNullable,
        requiredParameterCount: 1,
        typeParameters: calleeType.typeParameters
            .take(extensionTypeParameterCount)
            .toList());
    Arguments extensionArguments = engine.forest.createArguments(
        arguments.fileOffset, [arguments.positional.first],
        types: getExplicitExtensionTypeArguments(arguments));
    _inferInvocation(const UnknownType(), offset, extensionFunctionType,
        extensionArguments, hoistedExpressions,
        skipTypeArgumentInference: skipTypeArgumentInference,
        receiverType: receiverType,
        isImplicitExtensionMember: isImplicitExtensionMember,
        isImplicitCall: isImplicitCall,
        staticTarget: staticTarget,
        isExtensionMemberInvocation: true);
    Substitution extensionSubstitution = Substitution.fromPairs(
        extensionFunctionType.typeParameters, extensionArguments.types);

    List<TypeParameter> targetTypeParameters = const <TypeParameter>[];
    if (calleeType.typeParameters.length > extensionTypeParameterCount) {
      targetTypeParameters =
          calleeType.typeParameters.skip(extensionTypeParameterCount).toList();
    }
    FunctionType targetFunctionType = new FunctionType(
        calleeType.positionalParameters.skip(1).toList(),
        calleeType.returnType,
        library.nonNullable,
        requiredParameterCount: calleeType.requiredParameterCount - 1,
        namedParameters: calleeType.namedParameters,
        typeParameters: targetTypeParameters);
    targetFunctionType =
        extensionSubstitution.substituteType(targetFunctionType);
    Arguments targetArguments = engine.forest.createArguments(
        arguments.fileOffset, arguments.positional.skip(1).toList(),
        named: arguments.named, types: getExplicitTypeArguments(arguments));
    InvocationInferenceResult result = _inferInvocation(typeContext, offset,
        targetFunctionType, targetArguments, hoistedExpressions,
        isSpecialCasedBinaryOperator: isSpecialCasedBinaryOperator,
        isSpecialCasedTernaryOperator: isSpecialCasedTernaryOperator,
        skipTypeArgumentInference: skipTypeArgumentInference,
        isConst: isConst,
        isImplicitCall: isImplicitCall,
        staticTarget: staticTarget);
    arguments.positional.clear();
    arguments.positional.addAll(extensionArguments.positional);
    arguments.positional.addAll(targetArguments.positional);
    setParents(arguments.positional, arguments);
    // The `targetArguments.named` is the same list as `arguments.named` so
    // we just need to ensure that parent relations are realigned.
    setParents(arguments.named, arguments);
    arguments.types.clear();
    arguments.types.addAll(extensionArguments.types);
    arguments.types.addAll(targetArguments.types);
    return result;
  }

  /// Performs the type inference steps that are shared by all kinds of
  /// invocations (constructors, instance methods, and static methods).
  InvocationInferenceResult _inferInvocation(
      DartType typeContext,
      int offset,
      FunctionType calleeType,
      Arguments arguments,
      List<VariableDeclaration> hoistedExpressions,
      {bool isSpecialCasedBinaryOperator: false,
      bool isSpecialCasedTernaryOperator: false,
      DartType receiverType,
      bool skipTypeArgumentInference: false,
      bool isConst: false,
      bool isImplicitExtensionMember: false,
      bool isImplicitCall,
      Member staticTarget,
      bool isExtensionMemberInvocation: false}) {
    List<TypeParameter> calleeTypeParameters = calleeType.typeParameters;
    if (calleeTypeParameters.isNotEmpty) {
      // It's possible that one of the callee type parameters might match a type
      // that already exists as part of inference (e.g. the type of an
      // argument).  This might happen, for instance, in the case where a
      // function or method makes a recursive call to itself.  To avoid the
      // callee type parameters accidentally matching a type that already
      // exists, and creating invalid inference results, we need to create fresh
      // type parameters for the callee (see dartbug.com/31759).
      // TODO(paulberry): is it possible to find a narrower set of circumstances
      // in which me must do this, to avoid a performance regression?
      FreshTypeParameters fresh = getFreshTypeParameters(calleeTypeParameters);
      calleeType = fresh.applyToFunctionType(calleeType);
      calleeTypeParameters = fresh.freshTypeParameters;
    }
    List<DartType> explicitTypeArguments = getExplicitTypeArguments(arguments);
    bool inferenceNeeded = !skipTypeArgumentInference &&
        explicitTypeArguments == null &&
        calleeTypeParameters.isNotEmpty;
    bool typeChecksNeeded = !isTopLevel;
    List<DartType> inferredTypes;
    Substitution substitution;
    List<DartType> formalTypes;
    List<DartType> actualTypes;
    if (inferenceNeeded || typeChecksNeeded) {
      formalTypes = [];
      actualTypes = [];
    }
    if (inferenceNeeded) {
      if (isConst && typeContext != null) {
        typeContext = new TypeVariableEliminator(
                bottomType,
                isNonNullableByDefault
                    ? coreTypes.objectNullableRawType
                    : coreTypes.objectLegacyRawType)
            .substituteType(typeContext);
      }
      inferredTypes = new List<DartType>.filled(
          calleeTypeParameters.length, const UnknownType());
      typeSchemaEnvironment.inferGenericFunctionOrType(
          isNonNullableByDefault
              ? calleeType.returnType
              : legacyErasure(calleeType.returnType),
          calleeTypeParameters,
          null,
          null,
          typeContext,
          inferredTypes,
          library.library);
      substitution =
          Substitution.fromPairs(calleeTypeParameters, inferredTypes);
    } else if (explicitTypeArguments != null &&
        calleeTypeParameters.length == explicitTypeArguments.length) {
      substitution =
          Substitution.fromPairs(calleeTypeParameters, explicitTypeArguments);
    } else if (calleeTypeParameters.length != 0) {
      substitution = Substitution.fromPairs(
          calleeTypeParameters,
          new List<DartType>.filled(
              calleeTypeParameters.length, const DynamicType()));
    }
    bool isIdentical =
        staticTarget == typeSchemaEnvironment.coreTypes.identicalProcedure;
    // TODO(paulberry): if we are doing top level inference and type arguments
    // were omitted, report an error.
    for (int position = 0; position < arguments.positional.length; position++) {
      DartType formalType = getPositionalParameterType(calleeType, position);
      DartType inferredFormalType = substitution != null
          ? substitution.substituteType(formalType)
          : formalType;
      DartType inferredType;
      if (isImplicitExtensionMember && position == 0) {
        assert(
            receiverType != null,
            "No receiver type provided for implicit extension member "
            "invocation.");
        continue;
      } else {
        if (isSpecialCasedBinaryOperator) {
          inferredFormalType =
              typeSchemaEnvironment.getContextTypeOfSpecialCasedBinaryOperator(
                  typeContext, receiverType, inferredFormalType,
                  isNonNullableByDefault: isNonNullableByDefault);
        } else if (isSpecialCasedTernaryOperator) {
          inferredFormalType =
              typeSchemaEnvironment.getContextTypeOfSpecialCasedTernaryOperator(
                  typeContext, receiverType, inferredFormalType,
                  isNonNullableByDefault: isNonNullableByDefault);
        }
        ExpressionInferenceResult result = inferExpression(
            arguments.positional[position],
            isNonNullableByDefault
                ? inferredFormalType
                : legacyErasure(inferredFormalType),
            inferenceNeeded ||
                isSpecialCasedBinaryOperator ||
                isSpecialCasedTernaryOperator ||
                typeChecksNeeded);
        inferredType = result.inferredType == null || isNonNullableByDefault
            ? result.inferredType
            : legacyErasure(result.inferredType);
        Expression expression =
            _hoist(result.expression, inferredType, hoistedExpressions);
        if (isIdentical && arguments.positional.length == 2) {
          if (position == 0) {
            flowAnalysis?.equalityOp_rightBegin(expression, inferredType);
          } else {
            flowAnalysis?.equalityOp_end(
                arguments.parent, expression, inferredType);
          }
        }
        arguments.positional[position] = expression..parent = arguments;
      }
      if (inferenceNeeded || typeChecksNeeded) {
        formalTypes.add(formalType);
        actualTypes.add(inferredType);
      }
    }
    if (isSpecialCasedBinaryOperator) {
      calleeType = replaceReturnType(
          calleeType,
          typeSchemaEnvironment.getTypeOfSpecialCasedBinaryOperator(
              receiverType, actualTypes[0],
              isNonNullableByDefault: isNonNullableByDefault));
    } else if (isSpecialCasedTernaryOperator) {
      calleeType = replaceReturnType(
          calleeType,
          typeSchemaEnvironment.getTypeOfSpecialCasedTernaryOperator(
              receiverType, actualTypes[0], actualTypes[1], library.library));
    }
    for (NamedExpression namedArgument in arguments.named) {
      DartType formalType =
          getNamedParameterType(calleeType, namedArgument.name);
      DartType inferredFormalType = substitution != null
          ? substitution.substituteType(formalType)
          : formalType;
      ExpressionInferenceResult result = inferExpression(
          namedArgument.value,
          isNonNullableByDefault
              ? inferredFormalType
              : legacyErasure(inferredFormalType),
          inferenceNeeded || isSpecialCasedBinaryOperator || typeChecksNeeded);
      DartType inferredType =
          result.inferredType == null || isNonNullableByDefault
              ? result.inferredType
              : legacyErasure(result.inferredType);
      Expression expression =
          _hoist(result.expression, inferredType, hoistedExpressions);
      namedArgument.value = expression..parent = namedArgument;
      if (inferenceNeeded || typeChecksNeeded) {
        formalTypes.add(formalType);
        actualTypes.add(inferredType);
      }
    }

    // Check for and remove duplicated named arguments.
    List<NamedExpression> named = arguments.named;
    if (named.length == 2) {
      if (named[0].name == named[1].name) {
        String name = named[1].name;
        Expression error = helper.buildProblem(
            templateDuplicatedNamedArgument.withArguments(name),
            named[1].fileOffset,
            name.length);
        arguments.named = [new NamedExpression(named[1].name, error)];
        formalTypes.removeLast();
        actualTypes.removeLast();
      }
    } else if (named.length > 2) {
      Map<String, NamedExpression> seenNames = <String, NamedExpression>{};
      bool hasProblem = false;
      int namedTypeIndex = arguments.positional.length;
      List<NamedExpression> uniqueNamed = <NamedExpression>[];
      for (NamedExpression expression in named) {
        String name = expression.name;
        if (seenNames.containsKey(name)) {
          hasProblem = true;
          NamedExpression prevNamedExpression = seenNames[name];
          prevNamedExpression.value = helper.buildProblem(
              templateDuplicatedNamedArgument.withArguments(name),
              expression.fileOffset,
              name.length)
            ..parent = prevNamedExpression;
          formalTypes.removeAt(namedTypeIndex);
          actualTypes.removeAt(namedTypeIndex);
        } else {
          seenNames[name] = expression;
          uniqueNamed.add(expression);
          namedTypeIndex++;
        }
      }
      if (hasProblem) {
        arguments.named = uniqueNamed;
      }
    }

    if (inferenceNeeded) {
      typeSchemaEnvironment.inferGenericFunctionOrType(
          calleeType.returnType,
          calleeTypeParameters,
          formalTypes,
          actualTypes,
          typeContext,
          inferredTypes,
          library.library);
      assert(inferredTypes.every((type) => isKnown(type)),
          "Unknown type(s) in inferred types: $inferredTypes.");
      assert(inferredTypes.every((type) => !hasPromotedTypeVariable(type)),
          "Promoted type variable(s) in inferred types: $inferredTypes.");
      substitution =
          Substitution.fromPairs(calleeTypeParameters, inferredTypes);
      instrumentation?.record(uriForInstrumentation, offset, 'typeArgs',
          new InstrumentationValueForTypeArgs(inferredTypes));
      arguments.types.clear();
      arguments.types.addAll(inferredTypes);
      if (dataForTesting != null) {
        assert(arguments.fileOffset != TreeNode.noOffset);
        dataForTesting.typeInferenceResult.inferredTypeArguments[arguments] =
            inferredTypes;
      }
    }
    List<DartType> positionalArgumentTypes = [];
    List<NamedType> namedArgumentTypes = [];
    if (typeChecksNeeded && !identical(calleeType, unknownFunction)) {
      LocatedMessage argMessage = helper.checkArgumentsForType(
          calleeType, arguments, offset,
          isExtensionMemberInvocation: isExtensionMemberInvocation);
      if (argMessage != null) {
        return new WrapInProblemInferenceResult(
            const InvalidType(),
            const InvalidType(),
            argMessage.messageObject,
            argMessage.charOffset,
            argMessage.length,
            helper,
            isInapplicable: true);
      } else {
        // Argument counts and names match. Compare types.
        int positionalShift = isImplicitExtensionMember ? 1 : 0;
        int numPositionalArgs = arguments.positional.length - positionalShift;
        for (int i = 0; i < formalTypes.length; i++) {
          DartType formalType = formalTypes[i];
          DartType expectedType = substitution != null
              ? substitution.substituteType(formalType)
              : formalType;
          DartType actualType = actualTypes[i];
          Expression expression;
          NamedExpression namedExpression;
          if (i < numPositionalArgs) {
            expression = arguments.positional[positionalShift + i];
            positionalArgumentTypes.add(actualType);
          } else {
            namedExpression = arguments.named[i - numPositionalArgs];
            expression = namedExpression.value;
            namedArgumentTypes
                .add(new NamedType(namedExpression.name, actualType));
          }
          expression = ensureAssignable(expectedType, actualType, expression,
              isVoidAllowed: expectedType is VoidType,
              // TODO(johnniwinther): Specialize message for operator
              // invocations.
              errorTemplate: templateArgumentTypeNotAssignable,
              nullabilityErrorTemplate:
                  templateArgumentTypeNotAssignableNullability,
              nullabilityPartErrorTemplate:
                  templateArgumentTypeNotAssignablePartNullability,
              nullabilityNullErrorTemplate:
                  templateArgumentTypeNotAssignableNullabilityNull,
              nullabilityNullTypeErrorTemplate:
                  templateArgumentTypeNotAssignableNullabilityNullType);
          if (namedExpression == null) {
            arguments.positional[positionalShift + i] = expression
              ..parent = arguments;
          } else {
            namedExpression.value = expression..parent = namedExpression;
          }
        }
      }
    }
    DartType inferredType;
    if (substitution != null) {
      calleeType =
          substitution.substituteType(calleeType.withoutTypeParameters);
    }
    inferredType = calleeType.returnType;
    assert(
        !containsFreeFunctionTypeVariables(inferredType),
        "Inferred return type $inferredType contains free variables."
        "Inferred function type: $calleeType.");

    if (!isNonNullableByDefault) {
      inferredType = legacyErasure(inferredType);
      calleeType = legacyErasure(calleeType);
    }

    return new SuccessfulInferenceResult(inferredType, calleeType);
  }

  FunctionType inferLocalFunction(FunctionNode function, DartType typeContext,
      int fileOffset, DartType returnContext) {
    bool hasImplicitReturnType = false;
    if (returnContext == null) {
      hasImplicitReturnType = true;
      returnContext = const DynamicType();
    }
    if (!isTopLevel) {
      List<VariableDeclaration> positionalParameters =
          function.positionalParameters;
      for (int i = 0; i < positionalParameters.length; i++) {
        VariableDeclaration parameter = positionalParameters[i];
        flowAnalysis.declare(parameter, true);
        inferMetadataKeepingHelper(parameter, parameter.annotations);
        if (parameter.initializer != null) {
          ExpressionInferenceResult initializerResult = inferExpression(
              parameter.initializer, parameter.type, !isTopLevel);
          parameter.initializer = initializerResult.expression
            ..parent = parameter;
        }
      }
      for (VariableDeclaration parameter in function.namedParameters) {
        flowAnalysis.declare(parameter, true);
        inferMetadataKeepingHelper(parameter, parameter.annotations);
        ExpressionInferenceResult initializerResult =
            inferExpression(parameter.initializer, parameter.type, !isTopLevel);
        parameter.initializer = initializerResult.expression
          ..parent = parameter;
      }
    }

    // Let `<T0, ..., Tn>` be the set of type parameters of the closure (with
    // `n`=0 if there are no type parameters).
    List<TypeParameter> typeParameters = function.typeParameters;

    // Let `(P0 x0, ..., Pm xm)` be the set of formal parameters of the closure
    // (including required, positional optional, and named optional parameters).
    // If any type `Pi` is missing, denote it as `_`.
    List<VariableDeclaration> formals = function.positionalParameters.toList()
      ..addAll(function.namedParameters);

    // Let `B` denote the closure body.  If `B` is an expression function body
    // (`=> e`), treat it as equivalent to a block function body containing a
    // single `return` statement (`{ return e; }`).

    // Attempt to match `K` as a function type compatible with the closure (that
    // is, one having n type parameters and a compatible set of formal
    // parameters).  If there is a successful match, let `<S0, ..., Sn>` be the
    // set of matched type parameters and `(Q0, ..., Qm)` be the set of matched
    // formal parameter types, and let `N` be the return type.
    Substitution substitution;
    List<DartType> formalTypesFromContext =
        new List<DartType>.filled(formals.length, null);
    if (typeContext is FunctionType &&
        typeContext.typeParameters.length == typeParameters.length) {
      for (int i = 0; i < formals.length; i++) {
        if (i < function.positionalParameters.length) {
          formalTypesFromContext[i] =
              getPositionalParameterType(typeContext, i);
        } else {
          formalTypesFromContext[i] =
              getNamedParameterType(typeContext, formals[i].name);
        }
      }
      returnContext = typeContext.returnType;

      // Let `[T/S]` denote the type substitution where each `Si` is replaced
      // with the corresponding `Ti`.
      Map<TypeParameter, DartType> substitutionMap =
          <TypeParameter, DartType>{};
      for (int i = 0; i < typeContext.typeParameters.length; i++) {
        substitutionMap[typeContext.typeParameters[i]] =
            i < typeParameters.length
                ? new TypeParameterType.forAlphaRenaming(
                    typeContext.typeParameters[i], typeParameters[i])
                : const DynamicType();
      }
      substitution = Substitution.fromMap(substitutionMap);
    } else {
      // If the match is not successful because  `K` is `_`, let all `Si`, all
      // `Qi`, and `N` all be `_`.

      // If the match is not successful for any other reason, this will result
      // in a type error, so the implementation is free to choose the best
      // error recovery path.
      substitution = Substitution.empty;
    }

    // Define `Ri` as follows: if `Pi` is not `_`, let `Ri` be `Pi`.
    // Otherwise, if `Qi` is not `_`, let `Ri` be the greatest closure of
    // `Qi[T/S]` with respect to `?`.  Otherwise, let `Ri` be `dynamic`.
    for (int i = 0; i < formals.length; i++) {
      VariableDeclarationImpl formal = formals[i];
      if (formal.isImplicitlyTyped) {
        DartType inferredType;
        if (formalTypesFromContext[i] != null) {
          inferredType = computeGreatestClosure2(
              substitution.substituteType(formalTypesFromContext[i]));
          if (typeSchemaEnvironment.isSubtypeOf(
              inferredType,
              const NullType(),
              isNonNullableByDefault
                  ? SubtypeCheckMode.withNullabilities
                  : SubtypeCheckMode.ignoringNullabilities)) {
            inferredType = coreTypes.objectRawType(library.nullable);
          }
        } else {
          inferredType = const DynamicType();
        }
        instrumentation?.record(uriForInstrumentation, formal.fileOffset,
            'type', new InstrumentationValueForType(inferredType));
        formal.type = demoteTypeInLibrary(inferredType, library.library);
        if (dataForTesting != null) {
          dataForTesting.typeInferenceResult.inferredVariableTypes[formal] =
              formal.type;
        }
      }

      if (isNonNullableByDefault) {
        // If a parameter is a positional or named optional parameter and its
        // type is potentially non-nullable, it should have an initializer.
        bool isOptionalPositional = function.requiredParameterCount <= i &&
            i < function.positionalParameters.length;
        bool isOptionalNamed =
            i >= function.positionalParameters.length && !formal.isRequired;
        if ((isOptionalPositional || isOptionalNamed) &&
            formal.type.isPotentiallyNonNullable &&
            !formal.hasDeclaredInitializer) {
          library.addProblem(
              templateOptionalNonNullableWithoutInitializerError.withArguments(
                  formal.name, formal.type, isNonNullableByDefault),
              formal.fileOffset,
              formal.name.length,
              library.importUri);
        }
      }
    }

    if (isNonNullableByDefault) {
      for (VariableDeclarationImpl formal in function.namedParameters) {
        // Required named parameters shouldn't have initializers.
        if (formal.isRequired && formal.hasDeclaredInitializer) {
          library.addProblem(
              templateRequiredNamedParameterHasDefaultValueError
                  .withArguments(formal.name),
              formal.fileOffset,
              formal.name.length,
              library.importUri);
        }
      }
    }

    // Let `N'` be `N[T/S]`.  The [ClosureContext] constructor will adjust
    // accordingly if the closure is declared with `async`, `async*`, or
    // `sync*`.
    if (returnContext is! UnknownType) {
      returnContext = substitution.substituteType(returnContext);
    }

    // Apply type inference to `B` in return context `N’`, with any references
    // to `xi` in `B` having type `Pi`.  This produces `B’`.
    bool needToSetReturnType = hasImplicitReturnType;
    ClosureContext oldClosureContext = this.closureContext;
    ClosureContext closureContext = new ClosureContext(
        this, function.asyncMarker, returnContext, needToSetReturnType);
    this.closureContext = closureContext;
    StatementInferenceResult bodyResult = inferStatement(function.body);

    // If the closure is declared with `async*` or `sync*`, let `M` be the
    // least upper bound of the types of the `yield` expressions in `B’`, or
    // `void` if `B’` contains no `yield` expressions.  Otherwise, let `M` be
    // the least upper bound of the types of the `return` expressions in `B’`,
    // or `void` if `B’` contains no `return` expressions.
    DartType inferredReturnType;
    if (needToSetReturnType) {
      inferredReturnType = closureContext.inferReturnType(this,
          hasImplicitReturn: flowAnalysis.isReachable);
    }

    // Then the result of inference is `<T0, ..., Tn>(R0 x0, ..., Rn xn) B` with
    // type `<T0, ..., Tn>(R0, ..., Rn) -> M’` (with some of the `Ri` and `xi`
    // denoted as optional or named parameters, if appropriate).
    if (needToSetReturnType) {
      instrumentation?.record(uriForInstrumentation, fileOffset, 'returnType',
          new InstrumentationValueForType(inferredReturnType));
      function.returnType = inferredReturnType;
    }
    bodyResult = closureContext.handleImplicitReturn(
        this, function.body, bodyResult, fileOffset);
    function.futureValueType = closureContext.futureValueType;
    assert(
        !(isNonNullableByDefault &&
            function.asyncMarker == AsyncMarker.Async &&
            function.futureValueType == null),
        "No future value type computed.");

    if (bodyResult.hasChanged) {
      function.body = bodyResult.statement..parent = function;
    }
    this.closureContext = oldClosureContext;
    return function.computeFunctionType(library.nonNullable);
  }

  @override
  void inferMetadata(
      InferenceHelper helper, TreeNode parent, List<Expression> annotations) {
    if (annotations != null) {
      this.helper = helper;
      inferMetadataKeepingHelper(parent, annotations);
      this.helper = null;
    }
  }

  @override
  void inferMetadataKeepingHelper(
      TreeNode parent, List<Expression> annotations) {
    if (annotations != null) {
      for (int index = 0; index < annotations.length; index++) {
        ExpressionInferenceResult result = inferExpression(
            annotations[index], const UnknownType(), !isTopLevel);
        annotations[index] = result.expression..parent = parent;
      }
    }
  }

  StaticInvocation transformExtensionMethodInvocation(int fileOffset,
      ObjectAccessTarget target, Expression receiver, Arguments arguments) {
    assert(target.isExtensionMember || target.isNullableExtensionMember);
    Procedure procedure = target.member;
    return engine.forest.createStaticInvocation(
        fileOffset,
        target.member,
        engine.forest.createArgumentsForExtensionMethod(
            arguments.fileOffset,
            target.inferredExtensionTypeArguments.length,
            procedure.function.typeParameters.length -
                target.inferredExtensionTypeArguments.length,
            receiver,
            extensionTypeArguments: target.inferredExtensionTypeArguments,
            positionalArguments: arguments.positional,
            namedArguments: arguments.named,
            typeArguments: arguments.types));
  }

  ExpressionInferenceResult _inferDynamicInvocation(
      int fileOffset,
      Link<NullAwareGuard> nullAwareGuards,
      Expression receiver,
      Name name,
      Arguments arguments,
      DartType typeContext,
      List<VariableDeclaration> hoistedExpressions,
      {bool isImplicitCall}) {
    assert(isImplicitCall != null);
    InvocationInferenceResult result = inferInvocation(
        typeContext, fileOffset, unknownFunction, arguments,
        hoistedExpressions: hoistedExpressions,
        receiverType: const DynamicType(),
        isImplicitCall: isImplicitCall);
    assert(name != equalsName);
    Expression expression;
    if (useNewMethodInvocationEncoding) {
      expression = new DynamicInvocation(
          DynamicAccessKind.Dynamic, receiver, name, arguments)
        ..fileOffset = fileOffset;
    } else {
      expression = new MethodInvocation(receiver, name, arguments)
        ..fileOffset = fileOffset;
    }
    return createNullAwareExpressionInferenceResult(
        result.inferredType, result.applyResult(expression), nullAwareGuards);
  }

  ExpressionInferenceResult _inferNeverInvocation(
      int fileOffset,
      Link<NullAwareGuard> nullAwareGuards,
      Expression receiver,
      NeverType receiverType,
      Name name,
      Arguments arguments,
      DartType typeContext,
      List<VariableDeclaration> hoistedExpressions,
      {bool isImplicitCall}) {
    assert(isImplicitCall != null);
    InvocationInferenceResult result = inferInvocation(
        typeContext, fileOffset, unknownFunction, arguments,
        hoistedExpressions: hoistedExpressions,
        receiverType: receiverType,
        isImplicitCall: isImplicitCall);
    assert(name != equalsName);
    Expression expression;
    if (useNewMethodInvocationEncoding) {
      expression = new DynamicInvocation(
          DynamicAccessKind.Never, receiver, name, arguments)
        ..fileOffset = fileOffset;
    } else {
      expression = new MethodInvocation(receiver, name, arguments)
        ..fileOffset = fileOffset;
    }
    return createNullAwareExpressionInferenceResult(
        const NeverType.nonNullable(),
        result.applyResult(expression),
        nullAwareGuards);
  }

  ExpressionInferenceResult _inferMissingInvocation(
      int fileOffset,
      Link<NullAwareGuard> nullAwareGuards,
      Expression receiver,
      DartType receiverType,
      ObjectAccessTarget target,
      Name name,
      Arguments arguments,
      DartType typeContext,
      List<VariableDeclaration> hoistedExpressions,
      {bool isExpressionInvocation,
      bool isImplicitCall,
      Name implicitInvocationPropertyName}) {
    assert(target.isMissing || target.isAmbiguous);
    assert(isExpressionInvocation != null);
    assert(isImplicitCall != null);
    Expression error = createMissingMethodInvocation(
        fileOffset, receiver, receiverType, name, arguments,
        isExpressionInvocation: isExpressionInvocation,
        implicitInvocationPropertyName: implicitInvocationPropertyName,
        extensionAccessCandidates:
            target.isAmbiguous ? target.candidates : null);
    inferInvocation(typeContext, fileOffset, unknownFunction, arguments,
        hoistedExpressions: hoistedExpressions,
        receiverType: receiverType,
        isImplicitCall: isExpressionInvocation || isImplicitCall);
    assert(name != equalsName);
    // TODO(johnniwinther): Use InvalidType instead.
    return createNullAwareExpressionInferenceResult(
        const DynamicType(), error, nullAwareGuards);
  }

  ExpressionInferenceResult _inferExtensionInvocation(
      int fileOffset,
      Link<NullAwareGuard> nullAwareGuards,
      Expression receiver,
      DartType receiverType,
      ObjectAccessTarget target,
      Name name,
      Arguments arguments,
      DartType typeContext,
      List<VariableDeclaration> hoistedExpressions,
      {bool isImplicitCall}) {
    assert(isImplicitCall != null);
    assert(target.isExtensionMember || target.isNullableExtensionMember);
    DartType calleeType = getGetterType(target, receiverType);
    FunctionType functionType = getFunctionType(target, receiverType);

    if (target.extensionMethodKind == ProcedureKind.Getter) {
      StaticInvocation staticInvocation = transformExtensionMethodInvocation(
          fileOffset, target, receiver, new Arguments.empty());
      ExpressionInferenceResult result = inferMethodInvocation(
          fileOffset,
          nullAwareGuards,
          staticInvocation,
          calleeType,
          callName,
          arguments,
          typeContext,
          hoistedExpressions: hoistedExpressions,
          isExpressionInvocation: false,
          isImplicitCall: true,
          implicitInvocationPropertyName: name);

      if (!isTopLevel && target.isNullable) {
        // Handles cases like:
        //   C? c;
        //   c();
        // where there is an extension on C defined as:
        //   extension on C {
        //     void Function() get call => () {};
        //   }
        List<LocatedMessage> context = getWhyNotPromotedContext(
            flowAnalysis?.whyNotPromoted(receiver)(),
            staticInvocation,
            (type) => !type.isPotentiallyNullable);
        result = wrapExpressionInferenceResultInProblem(
            result,
            templateNullableExpressionCallError.withArguments(
                receiverType, isNonNullableByDefault),
            fileOffset,
            noLength,
            context: context);
      }

      return result;
    } else {
      StaticInvocation staticInvocation = transformExtensionMethodInvocation(
          fileOffset, target, receiver, arguments);
      InvocationInferenceResult result = inferInvocation(
          typeContext, fileOffset, functionType, staticInvocation.arguments,
          hoistedExpressions: hoistedExpressions,
          receiverType: receiverType,
          isImplicitExtensionMember: true,
          isImplicitCall: isImplicitCall,
          isExtensionMemberInvocation: true);
      if (!isTopLevel) {
        library.checkBoundsInStaticInvocation(staticInvocation,
            typeSchemaEnvironment, helper.uri, getTypeArgumentsInfo(arguments));
      }

      Expression replacement = result.applyResult(staticInvocation);
      if (!isTopLevel && target.isNullable) {
        List<LocatedMessage> context = getWhyNotPromotedContext(
            flowAnalysis?.whyNotPromoted(receiver)(),
            staticInvocation,
            (type) => !type.isPotentiallyNullable);
        if (isImplicitCall) {
          // Handles cases like:
          //   int? i;
          //   i();
          // where there is an extension:
          //   extension on int {
          //     void call() {}
          //   }
          replacement = helper.wrapInProblem(
              replacement,
              templateNullableExpressionCallError.withArguments(
                  receiverType, isNonNullableByDefault),
              fileOffset,
              noLength,
              context: context);
        } else {
          // Handles cases like:
          //   int? i;
          //   i.methodOnNonNullInt();
          // where `methodOnNonNullInt` is declared in an extension:
          //   extension on int {
          //     void methodOnNonNullInt() {}
          //   }
          replacement = helper.wrapInProblem(
              replacement,
              templateNullableMethodCallError.withArguments(
                  name.text, receiverType, isNonNullableByDefault),
              fileOffset,
              name.text.length,
              context: context);
        }
      }
      return createNullAwareExpressionInferenceResult(
          result.inferredType, replacement, nullAwareGuards);
    }
  }

  ExpressionInferenceResult _inferFunctionInvocation(
      int fileOffset,
      Link<NullAwareGuard> nullAwareGuards,
      Expression receiver,
      DartType receiverType,
      ObjectAccessTarget target,
      Arguments arguments,
      DartType typeContext,
      List<VariableDeclaration> hoistedExpressions,
      {bool isImplicitCall}) {
    assert(isImplicitCall != null);
    assert(target.isCallFunction || target.isNullableCallFunction);
    FunctionType declaredFunctionType = getFunctionType(target, receiverType);
    InvocationInferenceResult result = inferInvocation(
        typeContext, fileOffset, declaredFunctionType, arguments,
        hoistedExpressions: hoistedExpressions,
        receiverType: receiverType,
        isImplicitCall: isImplicitCall);
    Expression expression;
    String localName;
    if (useNewMethodInvocationEncoding) {
      DartType inferredFunctionType = result.functionType;
      if (result.isInapplicable) {
        // This was a function invocation whose arguments didn't match
        // the parameters.
        expression = new FunctionInvocation(
            FunctionAccessKind.Inapplicable, receiver, arguments,
            functionType: null)
          ..fileOffset = fileOffset;
      } else if (receiver is VariableGet) {
        VariableDeclaration variable = receiver.variable;
        TreeNode parent = variable.parent;
        if (parent is FunctionDeclaration) {
          assert(!identical(inferredFunctionType, unknownFunction),
              "Unknown function type for local function invocation.");
          localName = variable.name;
          expression = new LocalFunctionInvocation(variable, arguments,
              functionType: inferredFunctionType)
            ..fileOffset = receiver.fileOffset;
        }
      }
      expression ??= new FunctionInvocation(
          target.isNullableCallFunction
              ? FunctionAccessKind.Nullable
              : (inferredFunctionType == unknownFunction
                  ? FunctionAccessKind.Function
                  : FunctionAccessKind.FunctionType),
          receiver,
          arguments,
          functionType: inferredFunctionType == unknownFunction
              ? null
              : inferredFunctionType)
        ..fileOffset = fileOffset;
    } else {
      if (receiver is VariableGet) {
        VariableDeclaration variable = receiver.variable;
        TreeNode parent = variable.parent;
        if (parent is FunctionDeclaration) {
          // This is a local function invocation. Use the name in bounds
          // checking below.
          localName = variable.name;
        }
      }
      expression = new MethodInvocation(receiver, callName, arguments)
        ..fileOffset = fileOffset;
    }

    _checkBoundsInFunctionInvocation(
        declaredFunctionType, localName, arguments, fileOffset);

    Expression replacement = result.applyResult(expression);
    if (!isTopLevel && target.isNullableCallFunction) {
      List<LocatedMessage> context = getWhyNotPromotedContext(
          flowAnalysis?.whyNotPromoted(receiver)(),
          expression,
          (type) => !type.isPotentiallyNullable);
      if (isImplicitCall) {
        // Handles cases like:
        //   void Function()? f;
        //   f();
        replacement = helper.wrapInProblem(
            replacement,
            templateNullableExpressionCallError.withArguments(
                receiverType, isNonNullableByDefault),
            fileOffset,
            noLength,
            context: context);
      } else {
        // Handles cases like:
        //   void Function()? f;
        //   f.call();
        replacement = helper.wrapInProblem(
            replacement,
            templateNullableMethodCallError.withArguments(
                callName.text, receiverType, isNonNullableByDefault),
            fileOffset,
            callName.text.length,
            context: context);
      }
    }
    // TODO(johnniwinther): Check that type arguments against the bounds.
    return createNullAwareExpressionInferenceResult(
        result.inferredType, replacement, nullAwareGuards);
  }

  FunctionType _computeFunctionTypeForArguments(
      Arguments arguments, DartType type) {
    return new FunctionType(
        new List<DartType>.filled(arguments.positional.length, type),
        type,
        library.nonNullable,
        namedParameters: new List<NamedType>.generate(arguments.named.length,
            (int index) => new NamedType(arguments.named[index].name, type)));
  }

  ExpressionInferenceResult _inferInstanceMethodInvocation(
      int fileOffset,
      Link<NullAwareGuard> nullAwareGuards,
      Expression receiver,
      DartType receiverType,
      ObjectAccessTarget target,
      Arguments arguments,
      DartType typeContext,
      List<VariableDeclaration> hoistedExpressions,
      {bool isImplicitCall,
      bool isSpecialCasedBinaryOperator,
      bool isSpecialCasedTernaryOperator}) {
    assert(isImplicitCall != null);
    assert(isSpecialCasedBinaryOperator != null);
    assert(isSpecialCasedTernaryOperator != null);
    assert(target.isInstanceMember ||
        target.isObjectMember ||
        target.isNullableInstanceMember);
    Procedure method = target.member;
    assert(method.kind == ProcedureKind.Method,
        "Unexpected instance method $method");
    Name methodName = method.name;

    if (receiverType == const DynamicType()) {
      FunctionNode signature = method.function;
      if (arguments.positional.length < signature.requiredParameterCount ||
          arguments.positional.length > signature.positionalParameters.length) {
        target = const ObjectAccessTarget.dynamic();
        method = null;
      }
      for (NamedExpression argument in arguments.named) {
        if (!signature.namedParameters
            .any((declaration) => declaration.name == argument.name)) {
          target = const ObjectAccessTarget.dynamic();
          method = null;
        }
      }
      if (instrumentation != null && method != null) {
        instrumentation.record(uriForInstrumentation, fileOffset, 'target',
            new InstrumentationValueForMember(method));
      }
    }

    DartType calleeType = getGetterType(target, receiverType);
    FunctionType declaredFunctionType = getFunctionType(target, receiverType);

    bool contravariantCheck = false;
    if (receiver is! ThisExpression &&
        method != null &&
        returnedTypeParametersOccurNonCovariantly(
            method.enclosingClass, method.function.returnType)) {
      contravariantCheck = true;
    }
    InvocationInferenceResult result = inferInvocation(
        typeContext, fileOffset, declaredFunctionType, arguments,
        hoistedExpressions: hoistedExpressions,
        receiverType: receiverType,
        isImplicitCall: isImplicitCall,
        isSpecialCasedBinaryOperator: isSpecialCasedBinaryOperator,
        isSpecialCasedTernaryOperator: isSpecialCasedTernaryOperator);

    Expression expression;
    if (useNewMethodInvocationEncoding) {
      DartType inferredFunctionType = result.functionType;
      if (target.isDynamic) {
        // This was an Object member invocation whose arguments didn't match
        // the parameters.
        expression = new DynamicInvocation(
            DynamicAccessKind.Dynamic, receiver, methodName, arguments)
          ..fileOffset = fileOffset;
      } else if (result.isInapplicable) {
        // This was a method invocation whose arguments didn't match
        // the parameters.
        expression = new InstanceInvocation(
            InstanceAccessKind.Inapplicable, receiver, methodName, arguments,
            functionType: _computeFunctionTypeForArguments(
                arguments, const InvalidType()),
            interfaceTarget: method)
          ..fileOffset = fileOffset;
      } else {
        assert(
            inferredFunctionType is FunctionType &&
                !identical(unknownFunction, inferredFunctionType),
            "No function type found for $receiver.$methodName ($target) on "
            "$receiverType");
        InstanceAccessKind kind;
        switch (target.kind) {
          case ObjectAccessTargetKind.instanceMember:
            kind = InstanceAccessKind.Instance;
            break;
          case ObjectAccessTargetKind.nullableInstanceMember:
            kind = InstanceAccessKind.Nullable;
            break;
          case ObjectAccessTargetKind.objectMember:
            kind = InstanceAccessKind.Object;
            break;
          default:
            throw new UnsupportedError('Unexpected target kind $target');
        }
        expression = new InstanceInvocation(
            kind, receiver, methodName, arguments,
            functionType: inferredFunctionType, interfaceTarget: method)
          ..fileOffset = fileOffset;
      }
    } else {
      expression = new MethodInvocation(receiver, methodName, arguments, method)
        ..fileOffset = fileOffset;
    }
    Expression replacement;
    if (contravariantCheck) {
      // TODO(johnniwinther): Merge with the replacement computation below.
      replacement = new AsExpression(expression, result.inferredType)
        ..isTypeError = true
        ..isCovarianceCheck = true
        ..isForNonNullableByDefault = isNonNullableByDefault
        ..fileOffset = fileOffset;
      if (instrumentation != null) {
        int offset =
            arguments.fileOffset == -1 ? fileOffset : arguments.fileOffset;
        instrumentation.record(uriForInstrumentation, offset, 'checkReturn',
            new InstrumentationValueForType(result.inferredType));
      }
    } else {
      replacement = expression;
    }

    _checkBoundsInMethodInvocation(
        target, receiverType, calleeType, methodName, arguments, fileOffset);

    replacement = result.applyResult(replacement);
    if (!isTopLevel && target.isNullable) {
      List<LocatedMessage> context = getWhyNotPromotedContext(
          flowAnalysis?.whyNotPromoted(receiver)(),
          expression,
          (type) => !type.isPotentiallyNullable);
      if (isImplicitCall) {
        // Handles cases like:
        //   C? c;
        //   c();
        // Where C is defined as:
        //   class C {
        //     void call();
        //   }
        replacement = helper.wrapInProblem(
            replacement,
            templateNullableExpressionCallError.withArguments(
                receiverType, isNonNullableByDefault),
            fileOffset,
            noLength,
            context: context);
      } else {
        // Handles cases like:
        //   int? i;
        //   i.abs();
        replacement = helper.wrapInProblem(
            replacement,
            templateNullableMethodCallError.withArguments(
                methodName.text, receiverType, isNonNullableByDefault),
            fileOffset,
            methodName.text.length,
            context: context);
      }
    }

    return createNullAwareExpressionInferenceResult(
        result.inferredType, replacement, nullAwareGuards);
  }

  ExpressionInferenceResult _inferInstanceGetterInvocation(
      int fileOffset,
      Link<NullAwareGuard> nullAwareGuards,
      Expression receiver,
      DartType receiverType,
      ObjectAccessTarget target,
      Arguments arguments,
      DartType typeContext,
      List<VariableDeclaration> hoistedExpressions,
      {bool isExpressionInvocation}) {
    assert(isExpressionInvocation != null);
    assert(target.isInstanceMember ||
        target.isObjectMember ||
        target.isNullableInstanceMember);
    Procedure getter = target.member;
    assert(getter.kind == ProcedureKind.Getter);

    if (receiverType == const DynamicType() && getter is Procedure) {
      FunctionNode signature = getter.function;
      if (arguments.positional.length < signature.requiredParameterCount ||
          arguments.positional.length > signature.positionalParameters.length) {
        target = const ObjectAccessTarget.dynamic();
        getter = null;
      }
      for (NamedExpression argument in arguments.named) {
        if (!signature.namedParameters
            .any((declaration) => declaration.name == argument.name)) {
          target = const ObjectAccessTarget.dynamic();
          getter = null;
        }
      }
      if (instrumentation != null && getter != null) {
        instrumentation.record(uriForInstrumentation, fileOffset, 'target',
            new InstrumentationValueForMember(getter));
      }
    }

    DartType calleeType = getGetterType(target, receiverType);
    FunctionType functionType = getFunctionTypeForImplicitCall(calleeType);

    List<VariableDeclaration> locallyHoistedExpressions;
    if (hoistedExpressions == null && !isTopLevel) {
      // We don't hoist in top-level inference.
      hoistedExpressions = locallyHoistedExpressions = <VariableDeclaration>[];
    }
    if (arguments.positional.isNotEmpty || arguments.named.isNotEmpty) {
      receiver = _hoist(receiver, receiverType, hoistedExpressions);
    }

    Name originalName = getter.name;
    Expression originalReceiver = receiver;
    Member originalTarget = getter;
    Expression originalPropertyGet;
    if (useNewMethodInvocationEncoding) {
      InstanceAccessKind kind;
      switch (target.kind) {
        case ObjectAccessTargetKind.instanceMember:
          kind = InstanceAccessKind.Instance;
          break;
        case ObjectAccessTargetKind.nullableInstanceMember:
          kind = InstanceAccessKind.Nullable;
          break;
        case ObjectAccessTargetKind.objectMember:
          kind = InstanceAccessKind.Object;
          break;
        default:
          throw new UnsupportedError('Unexpected target kind $target');
      }
      originalPropertyGet = new InstanceGet(
          kind, originalReceiver, originalName,
          resultType: calleeType, interfaceTarget: originalTarget)
        ..fileOffset = fileOffset;
    } else {
      originalPropertyGet = new PropertyGet(receiver, getter.name, getter)
        ..fileOffset = fileOffset;
    }
    Expression propertyGet = originalPropertyGet;
    if (calleeType is! DynamicType &&
        receiver is! ThisExpression &&
        returnedTypeParametersOccurNonCovariantly(
            getter.enclosingClass, getter.function.returnType)) {
      propertyGet = new AsExpression(propertyGet, functionType)
        ..isTypeError = true
        ..isCovarianceCheck = true
        ..isForNonNullableByDefault = isNonNullableByDefault
        ..fileOffset = fileOffset;
      if (instrumentation != null) {
        int offset =
            arguments.fileOffset == -1 ? fileOffset : arguments.fileOffset;
        instrumentation.record(uriForInstrumentation, offset,
            'checkGetterReturn', new InstrumentationValueForType(functionType));
      }
    }
    ExpressionInferenceResult invocationResult = inferMethodInvocation(
        arguments.fileOffset,
        const Link<NullAwareGuard>(),
        propertyGet,
        calleeType,
        callName,
        arguments,
        typeContext,
        hoistedExpressions: hoistedExpressions,
        isExpressionInvocation: false,
        isImplicitCall: true,
        implicitInvocationPropertyName: getter.name);

    if (!isTopLevel && isExpressionInvocation) {
      Expression error = helper.buildProblem(
          templateImplicitCallOfNonMethod.withArguments(
              receiverType, isNonNullableByDefault),
          fileOffset,
          noLength);
      return new ExpressionInferenceResult(const DynamicType(), error);
    }

    if (!isTopLevel && target.isNullable) {
      // Handles cases like:
      //   C? c;
      //   c.foo();
      // Where C is defined as:
      //   class C {
      //     void Function() get foo => () {};
      //   }
      List<LocatedMessage> context = getWhyNotPromotedContext(
          flowAnalysis?.whyNotPromoted(receiver)(),
          invocationResult.expression,
          (type) => !type.isPotentiallyNullable);
      invocationResult = wrapExpressionInferenceResultInProblem(
          invocationResult,
          templateNullableExpressionCallError.withArguments(
              receiverType, isNonNullableByDefault),
          fileOffset,
          noLength,
          context: context);
    }

    if (!library.loader.target.backendTarget.supportsExplicitGetterCalls) {
      // TODO(johnniwinther): Remove this when dart2js/ddc supports explicit
      //  getter calls.
      Expression nullAwareAction = invocationResult.nullAwareAction;
      if (nullAwareAction is MethodInvocation &&
          nullAwareAction.receiver == originalPropertyGet) {
        invocationResult = new ExpressionInferenceResult(
            invocationResult.inferredType,
            new MethodInvocation(originalReceiver, originalName,
                nullAwareAction.arguments, originalTarget)
              ..fileOffset = nullAwareAction.fileOffset);
      } else if (nullAwareAction is InstanceInvocation &&
          nullAwareAction.receiver == originalPropertyGet) {
        // TODO(johnniwinther): Remove this when [MethodInvocation] is no longer
        // used and [originalPropertyGet] can be an [InstanceGet].
        InstanceGet instanceGet = originalPropertyGet;
        invocationResult = new ExpressionInferenceResult(
            invocationResult.inferredType,
            new InstanceGetterInvocation(instanceGet.kind, originalReceiver,
                originalName, nullAwareAction.arguments,
                interfaceTarget: originalTarget,
                functionType: nullAwareAction.functionType)
              ..fileOffset = nullAwareAction.fileOffset);
      } else if (nullAwareAction is DynamicInvocation &&
          nullAwareAction.receiver == originalPropertyGet) {
        // TODO(johnniwinther): Remove this when [MethodInvocation] is no longer
        // used and [originalPropertyGet] can be an [InstanceGet].
        InstanceGet instanceGet = originalPropertyGet;
        invocationResult = new ExpressionInferenceResult(
            invocationResult.inferredType,
            new InstanceGetterInvocation(instanceGet.kind, originalReceiver,
                originalName, nullAwareAction.arguments,
                interfaceTarget: originalTarget, functionType: null)
              ..fileOffset = nullAwareAction.fileOffset);
      } else if (nullAwareAction is FunctionInvocation &&
          nullAwareAction.receiver == originalPropertyGet) {
        // TODO(johnniwinther): Remove this when [MethodInvocation] is no longer
        // used and [originalPropertyGet] can be an [InstanceGet].
        InstanceGet instanceGet = originalPropertyGet;
        invocationResult = new ExpressionInferenceResult(
            invocationResult.inferredType,
            new InstanceGetterInvocation(instanceGet.kind, originalReceiver,
                originalName, nullAwareAction.arguments,
                interfaceTarget: originalTarget,
                functionType: nullAwareAction.functionType)
              ..fileOffset = nullAwareAction.fileOffset);
      }
    }
    invocationResult =
        _insertHoistedExpression(invocationResult, locallyHoistedExpressions);
    return createNullAwareExpressionInferenceResult(
        invocationResult.inferredType,
        invocationResult.expression,
        nullAwareGuards);
  }

  Expression _hoist(Expression expression, DartType type,
      List<VariableDeclaration> hoistedExpressions) {
    if (hoistedExpressions != null && expression is! ThisExpression) {
      VariableDeclaration variable = createVariable(expression, type);
      hoistedExpressions.add(variable);
      return createVariableGet(variable);
    }
    return expression;
  }

  ExpressionInferenceResult _insertHoistedExpression(
      ExpressionInferenceResult result,
      List<VariableDeclaration> hoistedExpressions) {
    if (hoistedExpressions != null && hoistedExpressions.isNotEmpty) {
      Expression expression = result.nullAwareAction;
      for (int index = hoistedExpressions.length - 1; index >= 0; index--) {
        expression = createLet(hoistedExpressions[index], expression);
      }
      return createNullAwareExpressionInferenceResult(
          result.inferredType, expression, result.nullAwareGuards);
    }
    return result;
  }

  ExpressionInferenceResult _inferInstanceFieldInvocation(
      int fileOffset,
      Link<NullAwareGuard> nullAwareGuards,
      Expression receiver,
      DartType receiverType,
      ObjectAccessTarget target,
      Arguments arguments,
      DartType typeContext,
      List<VariableDeclaration> hoistedExpressions,
      {bool isExpressionInvocation}) {
    assert(isExpressionInvocation != null);
    assert(target.isInstanceMember ||
        target.isObjectMember ||
        target.isNullableInstanceMember);
    Field field = target.member;

    DartType calleeType = getGetterType(target, receiverType);
    FunctionType functionType = getFunctionTypeForImplicitCall(calleeType);

    List<VariableDeclaration> locallyHoistedExpressions;
    if (hoistedExpressions == null && !isTopLevel) {
      // We don't hoist in top-level inference.
      hoistedExpressions = locallyHoistedExpressions = <VariableDeclaration>[];
    }
    if (arguments.positional.isNotEmpty || arguments.named.isNotEmpty) {
      receiver = _hoist(receiver, receiverType, hoistedExpressions);
    }

    Map<DartType, NonPromotionReason> Function() whyNotPromoted;
    if (!isTopLevel && target.isNullable) {
      // We won't report the error until later (after we have an
      // invocationResult), but we need to gather "why not promoted" info now,
      // before we tell flow analysis about the property get.
      whyNotPromoted = flowAnalysis?.whyNotPromoted(receiver);
    }

    Name originalName = field.name;
    Expression originalReceiver = receiver;
    Member originalTarget = field;
    Expression originalPropertyGet;
    if (useNewMethodInvocationEncoding) {
      InstanceAccessKind kind;
      switch (target.kind) {
        case ObjectAccessTargetKind.instanceMember:
          kind = InstanceAccessKind.Instance;
          break;
        case ObjectAccessTargetKind.nullableInstanceMember:
          kind = InstanceAccessKind.Nullable;
          break;
        case ObjectAccessTargetKind.objectMember:
          kind = InstanceAccessKind.Object;
          break;
        default:
          throw new UnsupportedError('Unexpected target kind $target');
      }
      originalPropertyGet = new InstanceGet(
          kind, originalReceiver, originalName,
          resultType: calleeType, interfaceTarget: originalTarget)
        ..fileOffset = fileOffset;
    } else {
      originalPropertyGet =
          new PropertyGet(originalReceiver, originalName, originalTarget)
            ..fileOffset = fileOffset;
    }
    flowAnalysis.propertyGet(originalPropertyGet, originalReceiver,
        originalName.text, originalTarget, calleeType);
    Expression propertyGet = originalPropertyGet;
    if (receiver is! ThisExpression &&
        calleeType is! DynamicType &&
        returnedTypeParametersOccurNonCovariantly(
            field.enclosingClass, field.type)) {
      propertyGet = new AsExpression(propertyGet, functionType)
        ..isTypeError = true
        ..isCovarianceCheck = true
        ..isForNonNullableByDefault = isNonNullableByDefault
        ..fileOffset = fileOffset;
      if (instrumentation != null) {
        int offset =
            arguments.fileOffset == -1 ? fileOffset : arguments.fileOffset;
        instrumentation.record(uriForInstrumentation, offset,
            'checkGetterReturn', new InstrumentationValueForType(functionType));
      }
    }

    ExpressionInferenceResult invocationResult = inferMethodInvocation(
        arguments.fileOffset,
        const Link<NullAwareGuard>(),
        propertyGet,
        calleeType,
        callName,
        arguments,
        typeContext,
        isExpressionInvocation: false,
        isImplicitCall: true,
        hoistedExpressions: hoistedExpressions,
        implicitInvocationPropertyName: field.name);

    if (!isTopLevel && isExpressionInvocation) {
      Expression error = helper.buildProblem(
          templateImplicitCallOfNonMethod.withArguments(
              receiverType, isNonNullableByDefault),
          fileOffset,
          noLength);
      return new ExpressionInferenceResult(const DynamicType(), error);
    }

    if (!isTopLevel && target.isNullable) {
      // Handles cases like:
      //   C? c;
      //   c.foo();
      // Where C is defined as:
      //   class C {
      //     void Function() foo;
      //     C(this.foo);
      //   }
      // TODO(paulberry): would it be better to report NullableMethodCallError
      // in this scenario?
      List<LocatedMessage> context = getWhyNotPromotedContext(whyNotPromoted(),
          invocationResult.expression, (type) => !type.isPotentiallyNullable);
      invocationResult = wrapExpressionInferenceResultInProblem(
          invocationResult,
          templateNullableExpressionCallError.withArguments(
              receiverType, isNonNullableByDefault),
          fileOffset,
          noLength,
          context: context);
    }

    if (!library.loader.target.backendTarget.supportsExplicitGetterCalls) {
      // TODO(johnniwinther): Remove this when dart2js/ddc supports explicit
      //  getter calls.
      Expression nullAwareAction = invocationResult.nullAwareAction;
      if (nullAwareAction is MethodInvocation &&
          nullAwareAction.receiver == originalPropertyGet) {
        invocationResult = new ExpressionInferenceResult(
            invocationResult.inferredType,
            new MethodInvocation(originalReceiver, originalName,
                nullAwareAction.arguments, originalTarget)
              ..fileOffset = nullAwareAction.fileOffset);
      } else if (nullAwareAction is InstanceInvocation &&
          nullAwareAction.receiver == originalPropertyGet) {
        invocationResult = new ExpressionInferenceResult(
            invocationResult.inferredType,
            new MethodInvocation(originalReceiver, originalName,
                nullAwareAction.arguments, originalTarget)
              ..fileOffset = nullAwareAction.fileOffset);
      } else if (nullAwareAction is DynamicInvocation &&
          nullAwareAction.receiver == originalPropertyGet) {
        invocationResult = new ExpressionInferenceResult(
            invocationResult.inferredType,
            new MethodInvocation(originalReceiver, originalName,
                nullAwareAction.arguments, originalTarget)
              ..fileOffset = nullAwareAction.fileOffset);
      } else if (nullAwareAction is FunctionInvocation &&
          nullAwareAction.receiver == originalPropertyGet) {
        invocationResult = new ExpressionInferenceResult(
            invocationResult.inferredType,
            new MethodInvocation(originalReceiver, originalName,
                nullAwareAction.arguments, originalTarget)
              ..fileOffset = nullAwareAction.fileOffset);
      }
    }
    invocationResult =
        _insertHoistedExpression(invocationResult, locallyHoistedExpressions);
    return createNullAwareExpressionInferenceResult(
        invocationResult.inferredType,
        invocationResult.expression,
        nullAwareGuards);
  }

  /// Performs the core type inference algorithm for method invocations.
  ExpressionInferenceResult inferMethodInvocation(
      int fileOffset,
      Link<NullAwareGuard> nullAwareGuards,
      Expression receiver,
      DartType receiverType,
      Name name,
      Arguments arguments,
      DartType typeContext,
      {bool isExpressionInvocation,
      bool isImplicitCall,
      Name implicitInvocationPropertyName,
      List<VariableDeclaration> hoistedExpressions}) {
    assert(isExpressionInvocation != null);
    assert(isImplicitCall != null);

    ObjectAccessTarget target = findInterfaceMember(
        receiverType, name, fileOffset,
        instrumented: true, includeExtensionMethods: true);

    switch (target.kind) {
      case ObjectAccessTargetKind.instanceMember:
      case ObjectAccessTargetKind.objectMember:
      case ObjectAccessTargetKind.nullableInstanceMember:
        Member member = target.member;
        if (member is Procedure) {
          if (member.kind == ProcedureKind.Getter) {
            return _inferInstanceGetterInvocation(
                fileOffset,
                nullAwareGuards,
                receiver,
                receiverType,
                target,
                arguments,
                typeContext,
                hoistedExpressions,
                isExpressionInvocation: isExpressionInvocation);
          } else {
            bool isSpecialCasedBinaryOperator =
                isSpecialCasedBinaryOperatorForReceiverType(
                    target, receiverType);
            return _inferInstanceMethodInvocation(
                fileOffset,
                nullAwareGuards,
                receiver,
                receiverType,
                target,
                arguments,
                typeContext,
                hoistedExpressions,
                isImplicitCall: isImplicitCall,
                isSpecialCasedBinaryOperator: isSpecialCasedBinaryOperator,
                isSpecialCasedTernaryOperator:
                    isSpecialCasedTernaryOperator(target));
          }
        } else {
          return _inferInstanceFieldInvocation(
              fileOffset,
              nullAwareGuards,
              receiver,
              receiverType,
              target,
              arguments,
              typeContext,
              hoistedExpressions,
              isExpressionInvocation: isExpressionInvocation);
        }
        break;
      case ObjectAccessTargetKind.callFunction:
      case ObjectAccessTargetKind.nullableCallFunction:
        return _inferFunctionInvocation(fileOffset, nullAwareGuards, receiver,
            receiverType, target, arguments, typeContext, hoistedExpressions,
            isImplicitCall: isImplicitCall);
      case ObjectAccessTargetKind.extensionMember:
      case ObjectAccessTargetKind.nullableExtensionMember:
        return _inferExtensionInvocation(
            fileOffset,
            nullAwareGuards,
            receiver,
            receiverType,
            target,
            name,
            arguments,
            typeContext,
            hoistedExpressions,
            isImplicitCall: isImplicitCall);
      case ObjectAccessTargetKind.ambiguous:
      case ObjectAccessTargetKind.missing:
        return _inferMissingInvocation(
            fileOffset,
            nullAwareGuards,
            receiver,
            receiverType,
            target,
            name,
            arguments,
            typeContext,
            hoistedExpressions,
            isExpressionInvocation: isExpressionInvocation,
            isImplicitCall: isImplicitCall,
            implicitInvocationPropertyName: implicitInvocationPropertyName);
      case ObjectAccessTargetKind.dynamic:
      case ObjectAccessTargetKind.invalid:
        return _inferDynamicInvocation(fileOffset, nullAwareGuards, receiver,
            name, arguments, typeContext, hoistedExpressions,
            isImplicitCall: isExpressionInvocation || isImplicitCall);
      case ObjectAccessTargetKind.never:
        return _inferNeverInvocation(fileOffset, nullAwareGuards, receiver,
            receiverType, name, arguments, typeContext, hoistedExpressions,
            isImplicitCall: isImplicitCall);
    }
    return unhandled(
        '$target', 'inferMethodInvocation', fileOffset, uriForInstrumentation);
  }

  void _checkBoundsInMethodInvocation(
      ObjectAccessTarget target,
      DartType receiverType,
      DartType calleeType,
      Name methodName,
      Arguments arguments,
      int fileOffset) {
    // If [arguments] were inferred, check them.
    if (!isTopLevel) {
      // We only perform checks in full inference.

      // [actualReceiverType], [interfaceTarget], and [actualMethodName] below
      // are for a workaround for the cases like the following:
      //
      //     class C1 { var f = new C2(); }
      //     class C2 { int call<X extends num>(X x) => 42; }
      //     main() { C1 c = new C1(); c.f("foobar"); }
      DartType actualReceiverType;
      Member interfaceTarget;
      Name actualMethodName;
      if (calleeType is InterfaceType) {
        actualReceiverType = calleeType;
        interfaceTarget = null;
        actualMethodName = callName;
      } else {
        actualReceiverType = receiverType;
        interfaceTarget = (target.isInstanceMember || target.isObjectMember)
            ? target.member
            : null;
        actualMethodName = methodName;
      }
      library.checkBoundsInMethodInvocation(
          actualReceiverType,
          typeSchemaEnvironment,
          classHierarchy,
          this,
          actualMethodName,
          interfaceTarget,
          arguments,
          helper.uri,
          fileOffset);
    }
  }

  void _checkBoundsInFunctionInvocation(FunctionType functionType,
      String localName, Arguments arguments, int fileOffset) {
    // If [arguments] were inferred, check them.
    if (!isTopLevel) {
      // We only perform checks in full inference.
      library.checkBoundsInFunctionInvocation(
          typeSchemaEnvironment,
          classHierarchy,
          this,
          functionType,
          localName,
          arguments,
          helper.uri,
          fileOffset);
    }
  }

  bool isSpecialCasedBinaryOperatorForReceiverType(
      ObjectAccessTarget target, DartType receiverType) {
    return (target.isInstanceMember ||
            target.isObjectMember ||
            target.isNullableInstanceMember) &&
        target.member is Procedure &&
        typeSchemaEnvironment.isSpecialCasesBinaryForReceiverType(
            target.member, receiverType,
            isNonNullableByDefault: isNonNullableByDefault);
  }

  bool isSpecialCasedTernaryOperator(ObjectAccessTarget target) {
    return (target.isInstanceMember ||
            target.isObjectMember ||
            target.isNullableInstanceMember) &&
        target.member is Procedure &&
        typeSchemaEnvironment.isSpecialCasedTernaryOperator(target.member,
            isNonNullableByDefault: isNonNullableByDefault);
  }

  /// Performs the core type inference algorithm for super method invocations.
  ExpressionInferenceResult inferSuperMethodInvocation(
      SuperMethodInvocation expression,
      DartType typeContext,
      Procedure procedure) {
    ObjectAccessTarget target = procedure != null
        ? new ObjectAccessTarget.interfaceMember(procedure,
            isPotentiallyNullable: false)
        : const ObjectAccessTarget.missing();
    int fileOffset = expression.fileOffset;
    Name methodName = expression.name;
    Arguments arguments = expression.arguments;
    DartType receiverType = thisType;
    bool isSpecialCasedBinaryOperator =
        isSpecialCasedBinaryOperatorForReceiverType(target, receiverType);
    DartType calleeType = getGetterType(target, receiverType);
    FunctionType functionType = getFunctionType(target, receiverType);
    if (procedure != null) {
      calleeType =
          computeTypeFromSuperClass(procedure.enclosingClass, calleeType);
      functionType =
          computeTypeFromSuperClass(procedure.enclosingClass, functionType);
    }
    if (isNonNullableByDefault &&
        expression.name == equalsName &&
        functionType.positionalParameters.length == 1) {
      // operator == always allows nullable arguments.
      functionType = new FunctionType([
        functionType.positionalParameters.single
            .withDeclaredNullability(library.nullable)
      ], functionType.returnType, functionType.declaredNullability);
    }
    InvocationInferenceResult result = inferInvocation(
        typeContext, fileOffset, functionType, arguments,
        isSpecialCasedBinaryOperator: isSpecialCasedBinaryOperator,
        receiverType: receiverType,
        isImplicitExtensionMember: false);
    DartType inferredType = result.inferredType;
    if (methodName.text == '==') {
      inferredType = coreTypes.boolRawType(library.nonNullable);
    }
    _checkBoundsInMethodInvocation(
        target, receiverType, calleeType, methodName, arguments, fileOffset);

    return new ExpressionInferenceResult(
        inferredType, result.applyResult(expression));
  }

  @override
  Expression inferParameterInitializer(
      InferenceHelper helper,
      Expression initializer,
      DartType declaredType,
      bool hasDeclaredInitializer) {
    assert(closureContext == null);
    this.helper = helper;
    assert(declaredType != null);
    ExpressionInferenceResult result =
        inferExpression(initializer, declaredType, true);
    if (hasDeclaredInitializer) {
      initializer = ensureAssignableResult(declaredType, result);
    }
    this.helper = null;
    return initializer;
  }

  /// Performs the core type inference algorithm for super property get.
  ExpressionInferenceResult inferSuperPropertyGet(
      SuperPropertyGet expression, DartType typeContext, Member member) {
    ObjectAccessTarget readTarget = member != null
        ? new ObjectAccessTarget.interfaceMember(member,
            isPotentiallyNullable: false)
        : const ObjectAccessTarget.missing();
    DartType receiverType = thisType;
    DartType inferredType = getGetterType(readTarget, receiverType);
    if (member != null) {
      inferredType =
          computeTypeFromSuperClass(member.enclosingClass, inferredType);
    }
    if (member is Procedure && member.kind == ProcedureKind.Method) {
      return instantiateTearOff(inferredType, typeContext, expression);
    }
    flowAnalysis.thisOrSuperPropertyGet(
        expression, expression.name.text, member, inferredType);
    return new ExpressionInferenceResult(inferredType, expression);
  }

  /// Performs type inference on the given [statement].
  ///
  /// Derived classes should override this method with logic that dispatches on
  /// the statement type and calls the appropriate specialized "infer" method.
  StatementInferenceResult inferStatement(Statement statement) {
    registerIfUnreachableForTesting(statement);

    // For full (non-top level) inference, we need access to the
    // ExpressionGeneratorHelper so that we can perform error recovery.
    if (!isTopLevel) assert(helper != null);
    InferenceVisitor visitor = new InferenceVisitor(this);
    if (statement is InternalStatement) {
      return statement.acceptInference(visitor);
    } else {
      return statement.accept(visitor);
    }
  }

  /// Performs the type inference steps necessary to instantiate a tear-off
  /// (if necessary).
  ExpressionInferenceResult instantiateTearOff(
      DartType tearoffType, DartType context, Expression expression) {
    if (tearoffType is FunctionType &&
        context is FunctionType &&
        context.typeParameters.isEmpty) {
      FunctionType functionType = tearoffType;
      List<TypeParameter> typeParameters = functionType.typeParameters;
      if (typeParameters.isNotEmpty) {
        List<DartType> inferredTypes = new List<DartType>.filled(
            typeParameters.length, const UnknownType());
        FunctionType instantiatedType = functionType.withoutTypeParameters;
        typeSchemaEnvironment.inferGenericFunctionOrType(instantiatedType,
            typeParameters, [], [], context, inferredTypes, library.library);
        if (!isTopLevel) {
          expression = new Instantiation(expression, inferredTypes)
            ..fileOffset = expression.fileOffset;
        }
        Substitution substitution =
            Substitution.fromPairs(typeParameters, inferredTypes);
        tearoffType = substitution.substituteType(instantiatedType);
      }
    }
    return new ExpressionInferenceResult(tearoffType, expression);
  }

  /// True if the returned [type] has non-covariant occurrences of any of
  /// [class_]'s type parameters.
  ///
  /// A non-covariant occurrence of a type parameter is either a contravariant
  /// or an invariant position.
  ///
  /// A contravariant position is to the left of an odd number of arrows. For
  /// example, T occurs contravariantly in T -> T0, T0 -> (T -> T1),
  /// (T0 -> T) -> T1 but not in (T -> T0) -> T1.
  ///
  /// An invariant position is without a bound of a type parameter. For example,
  /// T occurs invariantly in `S Function<S extends T>()` and
  /// `void Function<S extends C<T>>(S)`.
  static bool returnedTypeParametersOccurNonCovariantly(
      Class class_, DartType type) {
    if (class_.typeParameters.isEmpty) return false;
    IncludesTypeParametersNonCovariantly checker =
        new IncludesTypeParametersNonCovariantly(class_.typeParameters,
            // We are checking the returned type (field/getter type or return
            // type of a method) and this is a covariant position.
            initialVariance: Variance.covariant);
    return type.accept(checker);
  }

  /// Determines the dispatch category of a [MethodInvocation] and returns a
  /// boolean indicating whether an "as" check will need to be added due to
  /// contravariance.
  MethodContravarianceCheckKind preCheckInvocationContravariance(
      DartType receiverType, ObjectAccessTarget target,
      {bool isThisReceiver}) {
    assert(isThisReceiver != null);
    if (target.isInstanceMember || target.isObjectMember) {
      Member interfaceMember = target.member;
      if (interfaceMember is Field ||
          interfaceMember is Procedure &&
              interfaceMember.kind == ProcedureKind.Getter) {
        DartType getType = getGetterType(target, receiverType);
        if (getType is DynamicType) {
          return MethodContravarianceCheckKind.none;
        }
        if (!isThisReceiver) {
          if ((interfaceMember is Field &&
                  returnedTypeParametersOccurNonCovariantly(
                      interfaceMember.enclosingClass, interfaceMember.type)) ||
              (interfaceMember is Procedure &&
                  returnedTypeParametersOccurNonCovariantly(
                      interfaceMember.enclosingClass,
                      interfaceMember.function.returnType))) {
            return MethodContravarianceCheckKind.checkGetterReturn;
          }
        }
      } else if (!isThisReceiver &&
          interfaceMember is Procedure &&
          returnedTypeParametersOccurNonCovariantly(
              interfaceMember.enclosingClass,
              interfaceMember.function.returnType)) {
        return MethodContravarianceCheckKind.checkMethodReturn;
      }
    }
    return MethodContravarianceCheckKind.none;
  }

  /// If the given [type] is a [TypeParameterType], resolve it to its bound.
  DartType resolveTypeParameter(DartType type) {
    DartType resolveOneStep(DartType type) {
      if (type is TypeParameterType) {
        return type.bound;
      } else {
        return null;
      }
    }

    DartType resolved = resolveOneStep(type);
    if (resolved == null) return type;

    // Detect circularities using the tortoise-and-hare algorithm.
    type = resolved;
    DartType hare = resolveOneStep(type);
    if (hare == null) return type;
    while (true) {
      if (identical(type, hare)) {
        // We found a circularity.  Give up and return `dynamic`.
        return const DynamicType();
      }

      // Hare takes two steps
      DartType step1 = resolveOneStep(hare);
      if (step1 == null) return hare;
      DartType step2 = resolveOneStep(step1);
      if (step2 == null) return step1;
      hare = step2;

      // Tortoise takes one step
      type = resolveOneStep(type);
    }
  }

  DartType wrapFutureOrType(DartType type) {
    if (type is FutureOrType) {
      return type;
    }
    // TODO(paulberry): If [type] is a subtype of `Future`, should we just
    // return it unmodified?
    if (type == null) {
      return coreTypes.futureRawType(library.nullable);
    }
    return new FutureOrType(type, library.nonNullable);
  }

  DartType wrapFutureType(DartType type, Nullability nullability) {
    DartType typeWithoutFutureOr = type ?? const DynamicType();
    return new InterfaceType(
        coreTypes.futureClass, nullability, <DartType>[typeWithoutFutureOr]);
  }

  DartType wrapType(DartType type, Class class_, Nullability nullability) {
    return new InterfaceType(
        class_, nullability, <DartType>[type ?? const DynamicType()]);
  }

  /// Computes the `futureValueTypeSchema` for the type schema [type].
  ///
  /// This is the same as the [futureValueType] except that this handles
  /// the unknown type.
  DartType computeFutureValueTypeSchema(DartType type) {
    return type.accept1(new FutureValueTypeVisitor(unhandledTypeHandler:
        (DartType node, CoreTypes coreTypes,
            DartType Function(DartType node, CoreTypes coreTypes) recursor) {
      if (node is UnknownType) {
        // futureValueTypeSchema(_) = _.
        return node;
      }
      throw new UnsupportedError("Unsupported type '${node.runtimeType}'.");
    }), coreTypes);
  }

  Member _getInterfaceMember(
      Class class_, Name name, bool setter, int charOffset) {
    ClassMember classMember = engine.hierarchyBuilder
        .getInterfaceClassMember(class_, name, setter: setter);
    if (classMember != null) {
      if (classMember.isStatic) {
        classMember = null;
      } else if (classMember.isDuplicate) {
        if (!isTopLevel) {
          library.addProblem(
              templateDuplicatedDeclarationUse.withArguments(name.text),
              charOffset,
              name.text.length,
              helper.uri);
        }
        classMember = null;
      }
    }
    Member member = classMember?.getMember(engine.hierarchyBuilder);
    if (member == null && library.isPatch) {
      // TODO(johnniwinther): Injected members are currently not included
      // in the class hierarchy builder.
      member ??=
          classHierarchy.getInterfaceMember(class_, name, setter: setter);
    }
    return TypeInferenceEngine.resolveInferenceNode(member);
  }

  /// Determines if the given [expression]'s type is precisely known at compile
  /// time.
  ///
  /// If it is, an error message template is returned, which can be used by the
  /// caller to report an invalid cast.  Otherwise, `null` is returned.
  Template<Message Function(DartType, DartType, bool)>
      _getPreciseTypeErrorTemplate(Expression expression) {
    if (expression is ListLiteral) {
      return templateInvalidCastLiteralList;
    }
    if (expression is MapLiteral) {
      return templateInvalidCastLiteralMap;
    }
    if (expression is SetLiteral) {
      return templateInvalidCastLiteralSet;
    }
    if (expression is FunctionExpression) {
      return templateInvalidCastFunctionExpr;
    }
    if (expression is ConstructorInvocation) {
      return templateInvalidCastNewExpr;
    }
    if (expression is StaticGet) {
      Member target = expression.target;
      if (target is Procedure && target.kind == ProcedureKind.Method) {
        if (target.enclosingClass != null) {
          return templateInvalidCastStaticMethod;
        } else {
          return templateInvalidCastTopLevelFunction;
        }
      }
      return null;
    }
    if (expression is StaticTearOff) {
      Member target = expression.target;
      if (target.enclosingClass != null) {
        return templateInvalidCastStaticMethod;
      } else {
        return templateInvalidCastTopLevelFunction;
      }
    }
    if (expression is VariableGet) {
      VariableDeclaration variable = expression.variable;
      if (variable is VariableDeclarationImpl && variable.isLocalFunction) {
        return templateInvalidCastLocalFunction;
      }
    }
    return null;
  }

  bool _shouldTearOffCall(DartType contextType, DartType expressionType) {
    if (contextType is FutureOrType) {
      contextType = (contextType as FutureOrType).typeArgument;
    }
    if (contextType is FunctionType) return true;
    if (contextType is InterfaceType &&
        contextType.classNode == typeSchemaEnvironment.functionClass) {
      if (!typeSchemaEnvironment.isSubtypeOf(expressionType, contextType,
          SubtypeCheckMode.ignoringNullabilities)) {
        return true;
      }
    }
    return false;
  }

  Expression createMissingSuperIndexGet(int fileOffset, Expression index) {
    if (isTopLevel) {
      return engine.forest.createSuperMethodInvocation(fileOffset, indexGetName,
          null, engine.forest.createArguments(fileOffset, <Expression>[index]));
    } else {
      return helper.buildProblem(
          templateSuperclassHasNoMethod.withArguments(indexGetName.text),
          fileOffset,
          noLength);
    }
  }

  Expression createMissingSuperIndexSet(
      int fileOffset, Expression index, Expression value) {
    if (isTopLevel) {
      return engine.forest.createSuperMethodInvocation(
          fileOffset,
          indexSetName,
          null,
          engine.forest
              .createArguments(fileOffset, <Expression>[index, value]));
    } else {
      return helper.buildProblem(
          templateSuperclassHasNoMethod.withArguments(indexSetName.text),
          fileOffset,
          noLength);
    }
  }

  Expression _reportMissingOrAmbiguousMember(
      int fileOffset,
      int length,
      DartType receiverType,
      Name name,
      List<ExtensionAccessCandidate> extensionAccessCandidates,
      Template<Message Function(String, DartType, bool)> missingTemplate,
      Template<Message Function(String, DartType, bool)> ambiguousTemplate) {
    List<LocatedMessage> context;
    Template<Message Function(String, DartType, bool)> template =
        missingTemplate;
    if (extensionAccessCandidates != null) {
      context = extensionAccessCandidates
          .map((ExtensionAccessCandidate c) =>
              messageAmbiguousExtensionCause.withLocation(
                  c.memberBuilder.fileUri,
                  c.memberBuilder.charOffset,
                  name == unaryMinusName ? 1 : c.memberBuilder.name.length))
          .toList();
      template = ambiguousTemplate;
    }
    return helper.buildProblem(
        template.withArguments(name.text, resolveTypeParameter(receiverType),
            isNonNullableByDefault),
        fileOffset,
        length,
        context: context);
  }

  Expression createMissingMethodInvocation(int fileOffset, Expression receiver,
      DartType receiverType, Name name, Arguments arguments,
      {bool isExpressionInvocation,
      Name implicitInvocationPropertyName,
      List<ExtensionAccessCandidate> extensionAccessCandidates}) {
    assert(isExpressionInvocation != null);
    if (isTopLevel) {
      return engine.forest
          .createMethodInvocation(fileOffset, receiver, name, arguments);
    } else if (implicitInvocationPropertyName != null) {
      assert(extensionAccessCandidates == null);
      return helper.buildProblem(
          templateInvokeNonFunction
              .withArguments(implicitInvocationPropertyName.text),
          fileOffset,
          implicitInvocationPropertyName.text.length);
    } else {
      return _reportMissingOrAmbiguousMember(
          fileOffset,
          isExpressionInvocation ? noLength : name.text.length,
          receiverType,
          name,
          extensionAccessCandidates,
          receiverType is ExtensionType
              ? templateUndefinedExtensionMethod
              : templateUndefinedMethod,
          templateAmbiguousExtensionMethod);
    }
  }

  Expression createMissingPropertyGet(int fileOffset, Expression receiver,
      DartType receiverType, Name propertyName,
      {List<ExtensionAccessCandidate> extensionAccessCandidates}) {
    if (isTopLevel) {
      return engine.forest
          .createPropertyGet(fileOffset, receiver, propertyName);
    } else {
      Template<Message Function(String, DartType, bool)> templateMissing;
      if (receiverType is ExtensionType) {
        templateMissing = templateUndefinedExtensionGetter;
      } else {
        templateMissing = templateUndefinedGetter;
      }
      return _reportMissingOrAmbiguousMember(
          fileOffset,
          propertyName.text.length,
          receiverType,
          propertyName,
          extensionAccessCandidates,
          templateMissing,
          templateAmbiguousExtensionProperty);
    }
  }

  Expression createMissingPropertySet(int fileOffset, Expression receiver,
      DartType receiverType, Name propertyName, Expression value,
      {bool forEffect,
      List<ExtensionAccessCandidate> extensionAccessCandidates}) {
    assert(forEffect != null);
    if (isTopLevel) {
      return engine.forest.createPropertySet(
          fileOffset, receiver, propertyName, value,
          forEffect: forEffect);
    } else {
      Template<Message Function(String, DartType, bool)> templateMissing;
      if (receiverType is ExtensionType) {
        templateMissing = templateUndefinedExtensionSetter;
      } else {
        templateMissing = templateUndefinedSetter;
      }
      return _reportMissingOrAmbiguousMember(
          fileOffset,
          propertyName.text.length,
          receiverType,
          propertyName,
          extensionAccessCandidates,
          templateMissing,
          templateAmbiguousExtensionProperty);
    }
  }

  Expression createMissingIndexGet(int fileOffset, Expression receiver,
      DartType receiverType, Expression index,
      {List<ExtensionAccessCandidate> extensionAccessCandidates}) {
    if (isTopLevel) {
      return engine.forest.createIndexGet(fileOffset, receiver, index);
    } else {
      Template<Message Function(String, DartType, bool)> templateMissing;
      if (receiverType is ExtensionType) {
        templateMissing = templateUndefinedExtensionOperator;
      } else {
        templateMissing = templateUndefinedOperator;
      }
      return _reportMissingOrAmbiguousMember(
          fileOffset,
          noLength,
          receiverType,
          indexGetName,
          extensionAccessCandidates,
          templateMissing,
          templateAmbiguousExtensionOperator);
    }
  }

  Expression createMissingIndexSet(int fileOffset, Expression receiver,
      DartType receiverType, Expression index, Expression value,
      {bool forEffect,
      List<ExtensionAccessCandidate> extensionAccessCandidates}) {
    assert(forEffect != null);
    if (isTopLevel) {
      return engine.forest.createIndexSet(fileOffset, receiver, index, value,
          forEffect: forEffect);
    } else {
      Template<Message Function(String, DartType, bool)> templateMissing;
      if (receiverType is ExtensionType) {
        templateMissing = templateUndefinedExtensionOperator;
      } else {
        templateMissing = templateUndefinedOperator;
      }
      return _reportMissingOrAmbiguousMember(
          fileOffset,
          noLength,
          receiverType,
          indexSetName,
          extensionAccessCandidates,
          templateMissing,
          templateAmbiguousExtensionOperator);
    }
  }

  Expression createMissingBinary(int fileOffset, Expression left,
      DartType leftType, Name binaryName, Expression right,
      {List<ExtensionAccessCandidate> extensionAccessCandidates}) {
    assert(binaryName != equalsName);
    if (isTopLevel) {
      return engine.forest.createMethodInvocation(fileOffset, left, binaryName,
          engine.forest.createArguments(fileOffset, <Expression>[right]));
    } else {
      Template<Message Function(String, DartType, bool)> templateMissing;
      if (leftType is ExtensionType) {
        templateMissing = templateUndefinedExtensionOperator;
      } else {
        templateMissing = templateUndefinedOperator;
      }
      return _reportMissingOrAmbiguousMember(
          fileOffset,
          binaryName.text.length,
          leftType,
          binaryName,
          extensionAccessCandidates,
          templateMissing,
          templateAmbiguousExtensionOperator);
    }
  }

  Expression createMissingUnary(int fileOffset, Expression expression,
      DartType expressionType, Name unaryName,
      {List<ExtensionAccessCandidate> extensionAccessCandidates}) {
    if (isTopLevel) {
      return new UnaryExpression(unaryName, expression)
        ..fileOffset = fileOffset;
    } else {
      Template<Message Function(String, DartType, bool)> templateMissing;
      if (expressionType is ExtensionType) {
        templateMissing = templateUndefinedExtensionOperator;
      } else {
        templateMissing = templateUndefinedOperator;
      }
      return _reportMissingOrAmbiguousMember(
          fileOffset,
          unaryName == unaryMinusName ? 1 : unaryName.text.length,
          expressionType,
          unaryName,
          extensionAccessCandidates,
          templateMissing,
          templateAmbiguousExtensionOperator);
    }
  }

  /// Creates a `e == null` test for the expression [left] using the
  /// [fileOffset] as file offset for the created nodes and [equalsMember] as
  /// the interface target of the created method invocation.
  Expression createEqualsNull(
      int fileOffset, Expression left, Member equalsMember) {
    if (useNewMethodInvocationEncoding) {
      return new EqualsNull(left)..fileOffset = fileOffset;
    } else {
      return new MethodInvocation(
          left,
          equalsName,
          new Arguments(
              <Expression>[new NullLiteral()..fileOffset = fileOffset])
            ..fileOffset = fileOffset)
        ..fileOffset = fileOffset
        ..interfaceTarget = equalsMember;
    }
  }
}

abstract class MixinInferrer {
  final CoreTypes coreTypes;
  final TypeConstraintGatherer gatherer;

  MixinInferrer(this.coreTypes, this.gatherer);

  Supertype asInstantiationOf(Supertype type, Class superclass);

  void reportProblem(Message message, Class cls);

  void generateConstraints(
      Class mixinClass, Supertype baseType, Supertype mixinSupertype) {
    if (mixinSupertype.typeArguments.isEmpty) {
      // The supertype constraint isn't generic; it doesn't constrain anything.
    } else if (mixinSupertype.classNode.isAnonymousMixin) {
      // We have either a mixin declaration `mixin M<X0, ..., Xn> on S0, S1` or
      // a VM-style super mixin `abstract class M<X0, ..., Xn> extends S0 with
      // S1` where S0 and S1 are superclass constraints that possibly have type
      // arguments.
      //
      // It has been compiled by naming the superclass to either:
      //
      // abstract class S0&S1<...> extends Object implements S0, S1 {}
      // abstract class M<X0, ..., Xn> extends S0&S1<...> ...
      //
      // for a mixin declaration, or else:
      //
      // abstract class S0&S1<...> = S0 with S1;
      // abstract class M<X0, ..., Xn> extends S0&S1<...>
      //
      // for a VM-style super mixin.  The type parameters of S0&S1 are the X0,
      // ..., Xn that occurred free in S0 and S1.  Treat S0 and S1 as separate
      // supertype constraints by recursively calling this algorithm.
      //
      // In the Dart VM the mixin application classes themselves are all
      // eliminated by translating them to normal classes.  In that case, the
      // mixin appears as the only interface in the introduced class.  We
      // support three forms for the superclass constraints:
      //
      // abstract class S0&S1<...> extends Object implements S0, S1 {}
      // abstract class S0&S1<...> = S0 with S1;
      // abstract class S0&S1<...> extends S0 implements S1 {}
      Class mixinSuperclass = mixinSupertype.classNode;
      if (mixinSuperclass.mixedInType == null &&
          mixinSuperclass.implementedTypes.length != 1 &&
          (mixinSuperclass.superclass != coreTypes.objectClass ||
              mixinSuperclass.implementedTypes.length != 2)) {
        unexpected(
            'Compiler-generated mixin applications have a mixin or else '
                'implement exactly one type',
            '$mixinSuperclass implements '
                '${mixinSuperclass.implementedTypes.length} types',
            mixinSuperclass.fileOffset,
            mixinSuperclass.fileUri);
      }
      Substitution substitution = Substitution.fromSupertype(mixinSupertype);
      Supertype s0, s1;
      if (mixinSuperclass.implementedTypes.length == 2) {
        s0 = mixinSuperclass.implementedTypes[0];
        s1 = mixinSuperclass.implementedTypes[1];
      } else if (mixinSuperclass.implementedTypes.length == 1) {
        s0 = mixinSuperclass.supertype;
        s1 = mixinSuperclass.implementedTypes.first;
      } else {
        s0 = mixinSuperclass.supertype;
        s1 = mixinSuperclass.mixedInType;
      }
      s0 = substitution.substituteSupertype(s0);
      s1 = substitution.substituteSupertype(s1);
      generateConstraints(mixinClass, baseType, s0);
      generateConstraints(mixinClass, baseType, s1);
    } else {
      // Find the type U0 which is baseType as an instance of mixinSupertype's
      // class.
      Supertype supertype =
          asInstantiationOf(baseType, mixinSupertype.classNode);
      if (supertype == null) {
        reportProblem(
            templateMixinInferenceNoMatchingClass.withArguments(
                mixinClass.name,
                baseType.classNode.name,
                mixinSupertype.asInterfaceType,
                mixinClass.enclosingLibrary.isNonNullableByDefault),
            mixinClass);
        return;
      }
      InterfaceType u0 = Substitution.fromSupertype(baseType)
          .substituteSupertype(supertype)
          .asInterfaceType;
      // We want to solve U0 = S0 where S0 is mixinSupertype, but we only have
      // a subtype constraints.  Solve for equality by solving
      // both U0 <: S0 and S0 <: U0.
      InterfaceType s0 = mixinSupertype.asInterfaceType;

      gatherer.tryConstrainLower(s0, u0);
      gatherer.tryConstrainUpper(s0, u0);
    }
  }

  void infer(Class classNode) {
    Supertype mixedInType = classNode.mixedInType;
    assert(mixedInType.typeArguments.every((t) => t == const UnknownType()));
    // Note that we have no anonymous mixin applications, they have all
    // been named.  Note also that mixin composition has been translated
    // so that we only have mixin applications of the form `S with M`.
    Supertype baseType = classNode.supertype;
    Class mixinClass = mixedInType.classNode;
    Supertype mixinSupertype = mixinClass.supertype;
    // Generate constraints based on the mixin's supertype.
    generateConstraints(mixinClass, baseType, mixinSupertype);
    // Solve them to get a map from type parameters to upper and lower
    // bounds.
    Map<TypeParameter, TypeConstraint> result =
        gatherer.computeConstraints(classNode.enclosingLibrary);
    // Generate new type parameters with the solution as bounds.
    List<TypeParameter> parameters = mixinClass.typeParameters.map((p) {
      TypeConstraint constraint = result[p];
      // Because we solved for equality, a valid solution has a parameter
      // either unconstrained or else with identical upper and lower bounds.
      if (constraint != null && constraint.upper != constraint.lower) {
        reportProblem(
            templateMixinInferenceNoMatchingClass.withArguments(
                mixinClass.name,
                baseType.classNode.name,
                mixinSupertype.asInterfaceType,
                mixinClass.enclosingLibrary.isNonNullableByDefault),
            mixinClass);
        return p;
      }
      assert(constraint == null || constraint.upper == constraint.lower);
      bool exact =
          constraint != null && constraint.upper != const UnknownType();
      return new TypeParameter(
          p.name, exact ? constraint.upper : p.bound, p.defaultType);
    }).toList();
    // Bounds might mention the mixin class's type parameters so we have to
    // substitute them before calling instantiate to bounds.
    Substitution substitution = Substitution.fromPairs(
        mixinClass.typeParameters,
        new List<DartType>.generate(
            parameters.length,
            (i) => new TypeParameterType.forAlphaRenaming(
                mixinClass.typeParameters[i], parameters[i])));
    for (TypeParameter p in parameters) {
      p.bound = substitution.substituteType(p.bound);
    }
    // Use instantiate to bounds.
    List<DartType> bounds = calculateBounds(
        parameters, coreTypes.objectClass, classNode.enclosingLibrary);
    for (int i = 0; i < mixedInType.typeArguments.length; ++i) {
      mixedInType.typeArguments[i] = bounds[i];
    }
  }
}

/// The result of a statement inference.
class StatementInferenceResult {
  const StatementInferenceResult();

  factory StatementInferenceResult.single(Statement statement) =
      SingleStatementInferenceResult;

  factory StatementInferenceResult.multiple(
          int fileOffset, List<Statement> statements) =
      MultipleStatementInferenceResult;

  bool get hasChanged => false;

  Statement get statement =>
      throw new UnsupportedError('StatementInferenceResult.statement');

  int get statementCount =>
      throw new UnsupportedError('StatementInferenceResult.statementCount');

  List<Statement> get statements =>
      throw new UnsupportedError('StatementInferenceResult.statements');
}

class SingleStatementInferenceResult implements StatementInferenceResult {
  final Statement statement;

  SingleStatementInferenceResult(this.statement);

  bool get hasChanged => true;

  int get statementCount => 1;

  List<Statement> get statements =>
      throw new UnsupportedError('SingleStatementInferenceResult.statements');
}

class MultipleStatementInferenceResult implements StatementInferenceResult {
  final int fileOffset;
  final List<Statement> statements;

  MultipleStatementInferenceResult(this.fileOffset, this.statements);

  bool get hasChanged => true;

  Statement get statement => new Block(statements)..fileOffset = fileOffset;

  int get statementCount => statements.length;
}

/// Tells the inferred type and how the code should be transformed.
///
/// It is intended for use by generalized inference methods, such as
/// [TypeInferrerImpl.inferInvocation], where the input [Expression] isn't
/// available for rewriting.  So, instead of transforming the code, the result
/// of the inference provides a way to transform the code at the point of
/// invocation.
abstract class InvocationInferenceResult {
  DartType get inferredType;

  DartType get functionType;

  /// Applies the result of the inference to the expression being inferred.
  ///
  /// A successful result leaves [expression] intact, and an error detected
  /// during inference would wrap the expression into an [InvalidExpression].
  Expression applyResult(Expression expression);

  /// Returns `true` if the arguments of the call where not applicable to the
  /// target.
  bool get isInapplicable;
}

class SuccessfulInferenceResult implements InvocationInferenceResult {
  @override
  final DartType inferredType;

  @override
  final FunctionType functionType;

  SuccessfulInferenceResult(this.inferredType, this.functionType);

  @override
  Expression applyResult(Expression expression) => expression;

  @override
  bool get isInapplicable => false;
}

class WrapInProblemInferenceResult implements InvocationInferenceResult {
  @override
  final DartType inferredType;

  @override
  final DartType functionType;

  final Message message;

  final int fileOffset;

  final int length;

  final InferenceHelper helper;

  @override
  final bool isInapplicable;

  WrapInProblemInferenceResult(this.inferredType, this.functionType,
      this.message, this.fileOffset, this.length, this.helper,
      {this.isInapplicable})
      : assert(isInapplicable != null);

  @override
  Expression applyResult(Expression expression) {
    return helper.wrapInProblem(expression, message, fileOffset, length);
  }
}

/// The result of inference of a property get expression.
class PropertyGetInferenceResult {
  /// The main inference result.
  final ExpressionInferenceResult expressionInferenceResult;

  /// The property that was looked up, or `null` if no property was found.
  final Member member;

  PropertyGetInferenceResult(this.expressionInferenceResult, this.member);
}

/// The result of an expression inference.
class ExpressionInferenceResult {
  /// The inferred type of the expression.
  final DartType inferredType;

  /// The inferred expression.
  final Expression expression;

  ExpressionInferenceResult(this.inferredType, this.expression)
      : assert(expression != null);

  /// The guards used for null-aware access if the expression is part of a
  /// null-shorting.
  Link<NullAwareGuard> get nullAwareGuards => const Link<NullAwareGuard>();

  /// If the expression is part of a null-shorting, this is the action performed
  /// on the guarded variable, found as the first guard in [nullAwareGuards].
  /// Otherwise, this is the same as [expression].
  Expression get nullAwareAction => expression;

  DartType get nullAwareActionType => inferredType;

  ExpressionInferenceResult stopShorting() => this;

  String toString() => 'ExpressionInferenceResult($inferredType,$expression)';
}

/// A guard used for creating null-shorting null-aware actions.
class NullAwareGuard {
  /// The variable used to guard the null-aware action.
  final VariableDeclaration _nullAwareVariable;

  /// The file offset used for the null-test.
  int _nullAwareFileOffset;

  /// The [Member] used for the == call.
  final Member _nullAwareEquals;

  final TypeInferrerImpl _inferrer;

  NullAwareGuard(this._nullAwareVariable, this._nullAwareFileOffset,
      this._nullAwareEquals, this._inferrer)
      : assert(_nullAwareVariable != null),
        assert(_nullAwareFileOffset != null),
        assert(_nullAwareEquals != null),
        assert(_inferrer != null) {
    // Ensure the initializer of [_nullAwareVariable] is promoted to
    // non-nullable.
    _inferrer.flowAnalysis.nullAwareAccess_rightBegin(
        _nullAwareVariable.initializer, _nullAwareVariable.type);
    // Ensure [_nullAwareVariable] is promoted to non-nullable.
    // TODO(johnniwinther): Avoid creating a [VariableGet] to promote the
    // variable.
    VariableGet read = new VariableGet(_nullAwareVariable);
    _inferrer.flowAnalysis.variableRead(read, _nullAwareVariable);
    _inferrer.flowAnalysis
        .nullAwareAccess_rightBegin(read, _nullAwareVariable.type);
  }

  /// Creates the null-guarded application of [nullAwareAction] with the
  /// [inferredType].
  ///
  /// For an null-aware action `v.e` on the [_nullAwareVariable] `v` the created
  /// expression is
  ///
  ///     let v in v == null ? null : v.e
  ///
  Expression createExpression(
      DartType inferredType, Expression nullAwareAction) {
    // End non-nullable promotion of [_nullAwareVariable].
    _inferrer.flowAnalysis.nullAwareAccess_end();
    // End non-nullable promotion of the initializer of [_nullAwareVariable].
    _inferrer.flowAnalysis.nullAwareAccess_end();
    Expression equalsNull = _inferrer.createEqualsNull(_nullAwareFileOffset,
        createVariableGet(_nullAwareVariable), _nullAwareEquals);
    ConditionalExpression condition = new ConditionalExpression(
        equalsNull,
        new NullLiteral()..fileOffset = _nullAwareFileOffset,
        nullAwareAction,
        inferredType)
      ..fileOffset = _nullAwareFileOffset;
    return new Let(_nullAwareVariable, condition)
      ..fileOffset = _nullAwareFileOffset;
  }

  String toString() =>
      'NullAwareGuard($_nullAwareVariable,$_nullAwareFileOffset,'
      '$_nullAwareEquals)';
}

/// The result of an expression inference that is guarded with a null aware
/// variable.
class NullAwareExpressionInferenceResult implements ExpressionInferenceResult {
  /// The inferred type of the expression.
  final DartType inferredType;

  /// The inferred type of the [nullAwareAction].
  final DartType nullAwareActionType;

  @override
  final Link<NullAwareGuard> nullAwareGuards;

  @override
  final Expression nullAwareAction;

  NullAwareExpressionInferenceResult(this.inferredType,
      this.nullAwareActionType, this.nullAwareGuards, this.nullAwareAction)
      : assert(nullAwareGuards.isNotEmpty),
        assert(nullAwareAction != null);

  Expression get expression {
    throw new UnsupportedError('Shorting must be explicitly stopped before'
        'accessing the expression result of a '
        'NullAwareExpressionInferenceResult');
  }

  ExpressionInferenceResult stopShorting() {
    Expression expression = nullAwareAction;
    Link<NullAwareGuard> nullAwareGuard = nullAwareGuards;
    while (nullAwareGuard.isNotEmpty) {
      expression =
          nullAwareGuard.head.createExpression(inferredType, expression);
      nullAwareGuard = nullAwareGuard.tail;
    }
    return new ExpressionInferenceResult(inferredType, expression);
  }

  String toString() =>
      'NullAwareExpressionInferenceResult($inferredType,$nullAwareGuards,'
      '$nullAwareAction)';
}

enum ObjectAccessTargetKind {
  /// A valid access to a statically known instance member on a non-nullable
  /// receiver.
  instanceMember,

  /// A potentially nullable access to a statically known instance member. This
  /// is an erroneous case and a compile-time error is reported.
  nullableInstanceMember,

  /// A valid access to a statically known instance Object member on a
  /// potentially nullable receiver.
  objectMember,

  /// A (non-nullable) access to the `.call` method of a function. This is used
  /// for access on `Function` and on function types.
  callFunction,

  /// A potentially nullable access to the `.call` method of a function. This is
  /// an erroneous case and a compile-time error is reported.
  nullableCallFunction,

  /// A valid access to an extension member.
  extensionMember,

  /// A potentially nullable access to an extension member on an extension of
  /// a non-nullable type. This is an erroneous case and a compile-time error is
  /// reported.
  nullableExtensionMember,

  /// An access on a receiver of type `dynamic`.
  dynamic,

  /// An access on a receiver of type `Never`.
  never,

  /// An access on a receiver of an invalid type. This case is the result of
  /// a previously report error and no error is report this case.
  invalid,

  /// An access to a statically unknown instance member. This is an erroneous
  /// case and a compile-time error is reported.
  missing,

  /// An access to multiple extension members, none of which are most specific.
  /// This is an erroneous case and a compile-time error is reported.
  ambiguous,
}

/// Result for performing an access on an object, like `o.foo`, `o.foo()` and
/// `o.foo = ...`.
class ObjectAccessTarget {
  final ObjectAccessTargetKind kind;
  final Member member;

  const ObjectAccessTarget.internal(this.kind, this.member);

  /// Creates an access to the instance [member].
  factory ObjectAccessTarget.interfaceMember(Member member,
      {bool isPotentiallyNullable}) {
    assert(member != null);
    assert(isPotentiallyNullable != null);
    return new ObjectAccessTarget.internal(
        isPotentiallyNullable
            ? ObjectAccessTargetKind.nullableInstanceMember
            : ObjectAccessTargetKind.instanceMember,
        member);
  }

  /// Creates an access to the Object [member].
  factory ObjectAccessTarget.objectMember(Member member) {
    assert(member != null);
    return new ObjectAccessTarget.internal(
        ObjectAccessTargetKind.objectMember, member);
  }

  /// Creates an access to the extension [member].
  factory ObjectAccessTarget.extensionMember(
      Member member,
      Member tearoffTarget,
      ProcedureKind kind,
      List<DartType> inferredTypeArguments,
      {bool isPotentiallyNullable}) = ExtensionAccessTarget;

  /// Creates an access to a 'call' method on a function, i.e. a function
  /// invocation.
  const ObjectAccessTarget.callFunction()
      : this.internal(ObjectAccessTargetKind.callFunction, null);

  /// Creates an access to a 'call' method on a potentially nullable function,
  /// i.e. a function invocation.
  const ObjectAccessTarget.nullableCallFunction()
      : this.internal(ObjectAccessTargetKind.nullableCallFunction, null);

  /// Creates an access on a dynamic receiver type with no known target.
  const ObjectAccessTarget.dynamic()
      : this.internal(ObjectAccessTargetKind.dynamic, null);

  /// Creates an access on a receiver of type Never with no known target.
  const ObjectAccessTarget.never()
      : this.internal(ObjectAccessTargetKind.never, null);

  /// Creates an access with no target due to an invalid receiver type.
  ///
  /// This is not in itself an error but a consequence of another error.
  const ObjectAccessTarget.invalid()
      : this.internal(ObjectAccessTargetKind.invalid, null);

  /// Creates an access with no target.
  ///
  /// This is an error case.
  const ObjectAccessTarget.missing()
      : this.internal(ObjectAccessTargetKind.missing, null);

  /// Returns `true` if this is an access to an instance member.
  bool get isInstanceMember => kind == ObjectAccessTargetKind.instanceMember;

  /// Returns `true` if this is an access to an Object member.
  bool get isObjectMember => kind == ObjectAccessTargetKind.objectMember;

  /// Returns `true` if this is an access to an extension member.
  bool get isExtensionMember => kind == ObjectAccessTargetKind.extensionMember;

  /// Returns `true` if this is an access to the 'call' method on a function.
  bool get isCallFunction => kind == ObjectAccessTargetKind.callFunction;

  /// Returns `true` if this is an access to the 'call' method on a potentially
  /// nullable function.
  bool get isNullableCallFunction =>
      kind == ObjectAccessTargetKind.nullableCallFunction;

  /// Returns `true` if this is an access on a `dynamic` receiver type.
  bool get isDynamic => kind == ObjectAccessTargetKind.dynamic;

  /// Returns `true` if this is an access on a `Never` receiver type.
  bool get isNever => kind == ObjectAccessTargetKind.never;

  /// Returns `true` if this is an access on an invalid receiver type.
  bool get isInvalid => kind == ObjectAccessTargetKind.invalid;

  /// Returns `true` if this is an access with no target.
  bool get isMissing => kind == ObjectAccessTargetKind.missing;

  /// Returns `true` if this is an access with no unambiguous target. This
  /// occurs when an implicit extension access is ambiguous.
  bool get isAmbiguous => kind == ObjectAccessTargetKind.ambiguous;

  /// Returns `true` if this is an access to an instance member on a potentially
  /// nullable receiver.
  bool get isNullableInstanceMember =>
      kind == ObjectAccessTargetKind.nullableInstanceMember;

  /// Returns `true` if this is an access to an instance member on a potentially
  /// nullable receiver.
  bool get isNullableExtensionMember =>
      kind == ObjectAccessTargetKind.nullableExtensionMember;

  /// Returns `true` if this is an access to an instance member on a potentially
  /// nullable receiver.
  bool get isNullable =>
      isNullableInstanceMember ||
      isNullableCallFunction ||
      isNullableExtensionMember;

  /// Returns the candidates for an ambiguous extension access.
  List<ExtensionAccessCandidate> get candidates =>
      throw new UnsupportedError('ObjectAccessTarget.candidates');

  /// Returns the original procedure kind, if this is an extension method
  /// target.
  ///
  /// This is need because getters, setters, and methods are converted into
  /// top level methods, but access and invocation should still be treated as
  /// if they are the original procedure kind.
  ProcedureKind get extensionMethodKind =>
      throw new UnsupportedError('ObjectAccessTarget.extensionMethodKind');

  /// Returns inferred type arguments for the type parameters of an extension
  /// method that comes from the extension declaration.
  List<DartType> get inferredExtensionTypeArguments =>
      throw new UnsupportedError(
          'ObjectAccessTarget.inferredExtensionTypeArguments');

  /// Returns the member to use for a tearoff.
  ///
  /// This is currently used for extension methods.
  // TODO(johnniwinther): Normalize use by having `readTarget` and
  //  `invokeTarget`?
  Member get tearoffTarget =>
      throw new UnsupportedError('ObjectAccessTarget.tearoffTarget');

  @override
  String toString() => 'ObjectAccessTarget($kind,$member)';
}

class ExtensionAccessTarget extends ObjectAccessTarget {
  final Member tearoffTarget;
  final ProcedureKind extensionMethodKind;
  final List<DartType> inferredExtensionTypeArguments;

  ExtensionAccessTarget(Member member, this.tearoffTarget,
      this.extensionMethodKind, this.inferredExtensionTypeArguments,
      {bool isPotentiallyNullable: false})
      : super.internal(
            isPotentiallyNullable
                ? ObjectAccessTargetKind.nullableExtensionMember
                : ObjectAccessTargetKind.extensionMember,
            member);

  @override
  String toString() =>
      'ExtensionAccessTarget($kind,$member,$extensionMethodKind,'
      '$inferredExtensionTypeArguments)';
}

class AmbiguousExtensionAccessTarget extends ObjectAccessTarget {
  @override
  final List<ExtensionAccessCandidate> candidates;

  AmbiguousExtensionAccessTarget(this.candidates)
      : super.internal(ObjectAccessTargetKind.ambiguous, null);

  @override
  String toString() => 'AmbiguousExtensionAccessTarget($kind,$candidates)';
}

class ExtensionAccessCandidate {
  final MemberBuilder memberBuilder;
  final bool isPlatform;
  final DartType onType;
  final DartType onTypeInstantiateToBounds;
  final ObjectAccessTarget target;

  ExtensionAccessCandidate(this.memberBuilder, this.onType,
      this.onTypeInstantiateToBounds, this.target,
      {this.isPlatform})
      : assert(isPlatform != null);

  bool isMoreSpecificThan(TypeSchemaEnvironment typeSchemaEnvironment,
      ExtensionAccessCandidate other) {
    if (this.isPlatform == other.isPlatform) {
      // Both are platform or not platform.
      bool thisIsSubtype = typeSchemaEnvironment.isSubtypeOf(
          this.onType, other.onType, SubtypeCheckMode.withNullabilities);
      bool thisIsSupertype = typeSchemaEnvironment.isSubtypeOf(
          other.onType, this.onType, SubtypeCheckMode.withNullabilities);
      if (thisIsSubtype && !thisIsSupertype) {
        // This is subtype of other and not vice-versa.
        return true;
      } else if (thisIsSupertype && !thisIsSubtype) {
        // [other] is subtype of this and not vice-versa.
        return false;
      } else if (thisIsSubtype || thisIsSupertype) {
        thisIsSubtype = typeSchemaEnvironment.isSubtypeOf(
            this.onTypeInstantiateToBounds,
            other.onTypeInstantiateToBounds,
            SubtypeCheckMode.withNullabilities);
        thisIsSupertype = typeSchemaEnvironment.isSubtypeOf(
            other.onTypeInstantiateToBounds,
            this.onTypeInstantiateToBounds,
            SubtypeCheckMode.withNullabilities);
        if (thisIsSubtype && !thisIsSupertype) {
          // This is subtype of other and not vice-versa.
          return true;
        } else if (thisIsSupertype && !thisIsSubtype) {
          // [other] is subtype of this and not vice-versa.
          return false;
        }
      }
    } else if (other.isPlatform) {
      // This is not platform, [other] is: this  is more specific.
      return true;
    } else {
      // This is platform, [other] is not: other is more specific.
      return false;
    }
    // Neither is more specific than the other.
    return null;
  }
}

/// Describes assignability kind of one type to another.
enum AssignabilityKind {
  /// Unconditionally assignable.
  assignable,

  /// Assignable, but needs an implicit downcast.
  assignableCast,

  /// Assignable, but needs a tearoff due to a function context.
  assignableTearoff,

  /// Assignable, but needs both a tearoff and an implicit downcast.
  assignableTearoffCast,

  /// Unconditionally unassignable.
  unassignable,

  /// Trying to use void in an inappropriate context.
  unassignableVoid,

  /// The right-hand side type is precise, and the downcast will fail.
  unassignablePrecise,

  /// Unassignable, but needs a tearoff of "call" for better error reporting.
  unassignableTearoff,

  /// Unassignable because the tear-off can't be done on the nullable receiver.
  unassignableCantTearoff,

  /// Unassignable only because of nullability modifiers.
  unassignableNullability,

  /// Unassignable because of nullability and needs a tearoff of "call" for
  /// better error reporting.
  unassignableNullabilityTearoff,
}

class AssignabilityResult {
  final AssignabilityKind kind;
  final DartType subtype; // Can be null.
  final DartType supertype; // Can be null.

  const AssignabilityResult(this.kind)
      : subtype = null,
        supertype = null;

  AssignabilityResult.withTypes(this.kind, this.subtype, this.supertype);
}

/// Convenient way to return both a tear-off expression and its type.
class TypedTearoff {
  final DartType tearoffType;
  final Expression tearoff;

  TypedTearoff(this.tearoffType, this.tearoff);
}

FunctionType replaceReturnType(FunctionType functionType, DartType returnType) {
  return new FunctionType(functionType.positionalParameters, returnType,
      functionType.declaredNullability,
      requiredParameterCount: functionType.requiredParameterCount,
      namedParameters: functionType.namedParameters,
      typeParameters: functionType.typeParameters);
}

class InferredFunctionBody {
  final Statement body;
  final DartType futureValueType;

  InferredFunctionBody(this.body, this.futureValueType);
}

class _WhyNotPromotedVisitor
    implements
        NonPromotionReasonVisitor<LocatedMessage, Node, VariableDeclaration,
            DartType> {
  final TypeInferrerImpl inferrer;

  Member propertyReference;

  DartType propertyType;

  _WhyNotPromotedVisitor(this.inferrer);

  @override
  LocatedMessage visitDemoteViaExplicitWrite(
      DemoteViaExplicitWrite<VariableDeclaration> reason) {
    TreeNode node = reason.node as TreeNode;
    if (inferrer.dataForTesting != null) {
      inferrer.dataForTesting.flowAnalysisResult
          .nonPromotionReasonTargets[node] = reason.shortName;
    }
    int offset = node.fileOffset;
    return templateVariableCouldBeNullDueToWrite
        .withArguments(reason.variable.name, reason.documentationLink)
        .withLocation(inferrer.helper.uri, offset, noLength);
  }

  @override
  LocatedMessage visitPropertyNotPromoted(PropertyNotPromoted reason) {
    Object member = reason.propertyMember;
    if (member is Member) {
      propertyReference = member;
      propertyType = reason.staticType;
      return templateFieldNotPromoted
          .withArguments(reason.propertyName, reason.documentationLink)
          .withLocation(member.fileUri, member.fileOffset, noLength);
    } else {
      assert(member == null,
          'Unrecognized property member: ${member.runtimeType}');
      return null;
    }
  }

  @override
  LocatedMessage visitThisNotPromoted(ThisNotPromoted reason) {
    return templateThisNotPromoted
        .withArguments(reason.documentationLink)
        .withoutLocation();
  }
}
