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

import 'package:kernel/src/replacement_visitor.dart';

import '../ast.dart' hide MapEntry;

import '../type_algebra.dart' show Substitution, substitute;

import '../type_environment.dart' show SubtypeCheckMode, TypeEnvironment;

import '../util/graph.dart' show Graph, computeStrongComponents;

import '../visitor.dart' show DartTypeVisitor, DartTypeVisitor1;

import 'legacy_erasure.dart';

class TypeVariableGraph extends Graph<int> {
  late List<int> vertices;
  List<TypeParameter> typeParameters;
  List<DartType> bounds;

  // `edges[i]` is the list of indices of type variables that reference the type
  // variable with the index `i` in their bounds.
  late List<List<int>> edges;

  TypeVariableGraph(this.typeParameters, this.bounds) {
    assert(typeParameters.length == bounds.length);

    vertices = new List<int>.filled(
        typeParameters.length,
        // Dummy value.
        -1);
    Map<TypeParameter, int> typeParameterIndices = <TypeParameter, int>{};
    edges = new List<List<int>>.filled(typeParameters.length,
        // Dummy value.
        const []);
    for (int i = 0; i < vertices.length; i++) {
      vertices[i] = i;
      typeParameterIndices[typeParameters[i]] = i;
      edges[i] = <int>[];
    }

    for (int i = 0; i < vertices.length; i++) {
      OccurrenceCollectorVisitor collector =
          new OccurrenceCollectorVisitor(typeParameters.toSet());
      collector.visit(bounds[i]);
      for (TypeParameter typeParameter in collector.occurred) {
        edges[typeParameterIndices[typeParameter]!].add(i);
      }
    }
  }

  Iterable<int> neighborsOf(int index) {
    return edges[index];
  }
}

class OccurrenceCollectorVisitor extends DartTypeVisitor<void> {
  final Set<TypeParameter> typeParameters;
  Set<TypeParameter> occurred = new Set<TypeParameter>();

  OccurrenceCollectorVisitor(this.typeParameters);

  void visit(DartType node) => node.accept(this);

  void visitNamedType(NamedType node) {
    node.type.accept(this);
  }

  void visitInvalidType(InvalidType node);
  void visitDynamicType(DynamicType node);
  void visitVoidType(VoidType node);

  void visitInterfaceType(InterfaceType node) {
    for (DartType argument in node.typeArguments) {
      argument.accept(this);
    }
  }

  void visitTypedefType(TypedefType node) {
    for (DartType argument in node.typeArguments) {
      argument.accept(this);
    }
  }

  void visitFunctionType(FunctionType node) {
    for (TypeParameter typeParameter in node.typeParameters) {
      typeParameter.bound.accept(this);
      typeParameter.defaultType.accept(this);
    }
    for (DartType parameter in node.positionalParameters) {
      parameter.accept(this);
    }
    for (NamedType namedParameter in node.namedParameters) {
      namedParameter.type.accept(this);
    }
    node.returnType.accept(this);
  }

  void visitTypeParameterType(TypeParameterType node) {
    if (typeParameters.contains(node.parameter)) {
      occurred.add(node.parameter);
    }
  }

  @override
  void defaultDartType(DartType node) {}
}

DartType instantiateToBounds(
    DartType type, Class objectClass, Library contextLibrary) {
  if (type is InterfaceType) {
    if (type.typeArguments.isEmpty) return type;
    for (DartType typeArgument in type.typeArguments) {
      // If at least one of the arguments is not dynamic, we assume that the
      // type is not raw and does not need instantiation of its type parameters
      // to their bounds.
      if (typeArgument is! DynamicType) {
        return type;
      }
    }
    return new InterfaceType.byReference(
        type.className,
        type.nullability,
        calculateBounds(
            type.classNode.typeParameters, objectClass, contextLibrary));
  }
  if (type is TypedefType) {
    if (type.typeArguments.isEmpty) return type;
    for (DartType typeArgument in type.typeArguments) {
      if (typeArgument is! DynamicType) {
        return type;
      }
    }
    return new TypedefType.byReference(
        type.typedefReference,
        type.nullability,
        calculateBounds(
            type.typedefNode.typeParameters, objectClass, contextLibrary));
  }
  return type;
}

/// Calculates bounds to be provided as type arguments in place of missing type
/// arguments on raw types with the given type parameters.
///
/// See the [description]
/// (https://github.com/dart-lang/sdk/blob/master/docs/language/informal/instantiate-to-bound.md)
/// of the algorithm for details.
List<DartType> calculateBounds(List<TypeParameter> typeParameters,
    Class objectClass, Library contextLibrary) {
  return calculateBoundsInternal(typeParameters, objectClass,
      isNonNullableByDefault: contextLibrary.isNonNullableByDefault);
}

List<DartType> calculateBoundsInternal(
    List<TypeParameter> typeParameters, Class objectClass,
    {required bool isNonNullableByDefault}) {
  // ignore: unnecessary_null_comparison
  assert(isNonNullableByDefault != null);

  List<DartType> bounds =
      new List<DartType>.filled(typeParameters.length, dummyDartType);
  for (int i = 0; i < typeParameters.length; i++) {
    DartType bound = typeParameters[i].bound;
    bool isContravariant = typeParameters[i].variance == Variance.contravariant;
    if (identical(bound, TypeParameter.unsetBoundSentinel)) {
      bound = isNonNullableByDefault && isContravariant
          ? const NeverType.nonNullable()
          : const DynamicType();
    } else if (bound is InterfaceType && bound.classNode == objectClass) {
      DartType defaultType = typeParameters[i].defaultType;
      if (!(defaultType is InterfaceType &&
          defaultType.classNode == objectClass)) {
        bound = isNonNullableByDefault && isContravariant
            ? const NeverType.nonNullable()
            : const DynamicType();
      }
    }
    bounds[i] = bound;
  }

  TypeVariableGraph graph = new TypeVariableGraph(typeParameters, bounds);
  List<List<int>> stronglyConnected = computeStrongComponents(graph);
  final DartType topType = const DynamicType();
  final DartType bottomType = isNonNullableByDefault
      ? const NeverType.nonNullable()
      : const NeverType.legacy();
  for (List<int> component in stronglyConnected) {
    Map<TypeParameter, DartType> upperBounds = <TypeParameter, DartType>{};
    Map<TypeParameter, DartType> lowerBounds = <TypeParameter, DartType>{};
    for (int typeParameterIndex in component) {
      upperBounds[typeParameters[typeParameterIndex]] = topType;
      lowerBounds[typeParameters[typeParameterIndex]] = bottomType;
    }
    Substitution substitution =
        Substitution.fromUpperAndLowerBounds(upperBounds, lowerBounds);
    for (int typeParameterIndex in component) {
      bounds[typeParameterIndex] = substitution.substituteType(
          bounds[typeParameterIndex],
          contravariant: typeParameters[typeParameterIndex].variance ==
              Variance.contravariant);
    }
  }

  for (int i = 0; i < typeParameters.length; i++) {
    Map<TypeParameter, DartType> upperBounds = <TypeParameter, DartType>{};
    Map<TypeParameter, DartType> lowerBounds = <TypeParameter, DartType>{};
    upperBounds[typeParameters[i]] = bounds[i];
    lowerBounds[typeParameters[i]] = bottomType;
    Substitution substitution =
        Substitution.fromUpperAndLowerBounds(upperBounds, lowerBounds);
    for (int j = 0; j < typeParameters.length; j++) {
      bounds[j] = substitution.substituteType(bounds[j],
          contravariant: typeParameters[j].variance == Variance.contravariant);
    }
  }

  return bounds;
}

class TypeArgumentIssue {
  /// The index for type argument within the passed type arguments.
  final int index;

  /// The type argument that violated the bound.
  final DartType argument;

  /// The type parameter with the bound that was violated.
  final TypeParameter typeParameter;

  /// The enclosing type of the issue, that is, the one with [typeParameter].
  final DartType? enclosingType;

  /// The type computed from [enclosingType] for the super-boundness check.
  ///
  /// This field can be null.  [invertedType] is supposed to enhance error
  /// messages, providing the auxiliary type for super-boundness checks for the
  /// user.  It is set to null if it's not helpful, for example, if
  /// [enclosingType] is well-bounded or is strictly required to be
  /// regular-bounded, so the super-boundness check is skipped.  It is set to
  /// null also if the inversion didn't change the type at all, and it's not
  /// helpful to show the same type to the user.
  DartType? invertedType;

  final bool isGenericTypeAsArgumentIssue;

  TypeArgumentIssue(
      this.index, this.argument, this.typeParameter, this.enclosingType,
      {this.invertedType, this.isGenericTypeAsArgumentIssue = false});

  int get hashCode {
    int hash = 0x3fffffff & index;
    hash = 0x3fffffff & (hash * 31 + (hash ^ argument.hashCode));
    hash = 0x3fffffff & (hash * 31 + (hash ^ typeParameter.hashCode));
    hash = 0x3fffffff & (hash * 31 + (hash ^ enclosingType.hashCode));
    return hash;
  }

  bool operator ==(Object other) {
    assert(other is TypeArgumentIssue);
    return other is TypeArgumentIssue &&
        index == other.index &&
        argument == other.argument &&
        typeParameter == other.typeParameter &&
        enclosingType == other.enclosingType;
  }

  String toString() {
    return "TypeArgumentIssue(index=${index}, argument=${argument}, "
        "typeParameter=${typeParameter}, enclosingType=${enclosingType}";
  }
}

// Finds type arguments that don't follow the rules of well-boundness.
//
// [bottomType] should be either Null or Never, depending on what should be
// taken for the bottom type at the call site.  The bottom type is used in the
// checks for super-boundness for construction of the auxiliary type.  For
// details see Dart Language Specification, Section 14.3.2 The Instantiation to
// Bound Algorithm.
List<TypeArgumentIssue> findTypeArgumentIssues(DartType type,
    TypeEnvironment typeEnvironment, SubtypeCheckMode subtypeCheckMode,
    {bool allowSuperBounded = false,
    required bool isNonNullableByDefault,
    required bool areGenericArgumentsAllowed}) {
  // ignore: unnecessary_null_comparison
  assert(isNonNullableByDefault != null);
  // ignore: unnecessary_null_comparison
  assert(areGenericArgumentsAllowed != null);

  List<TypeParameter> variables = const <TypeParameter>[];
  List<DartType> arguments = const <DartType>[];
  List<TypeArgumentIssue> typedefRhsResult = const <TypeArgumentIssue>[];

  if (type is FunctionType && type.typedefType != null) {
    // [type] is a function type that is an application of a parametrized
    // typedef.  We need to check both the l.h.s. and the r.h.s. of the
    // definition in that case.  For details, see [link]
    // (https://github.com/dart-lang/sdk/blob/master/docs/language/informal/super-bounded-types.md).
    FunctionType functionType = type;
    FunctionType cloned = new FunctionType(functionType.positionalParameters,
        functionType.returnType, functionType.nullability,
        namedParameters: functionType.namedParameters,
        typeParameters: functionType.typeParameters,
        requiredParameterCount: functionType.requiredParameterCount,
        typedefType: null);
    typedefRhsResult = findTypeArgumentIssues(
        cloned, typeEnvironment, subtypeCheckMode,
        allowSuperBounded: true,
        isNonNullableByDefault: isNonNullableByDefault,
        areGenericArgumentsAllowed: areGenericArgumentsAllowed);
    type = functionType.typedefType!;
  }

  if (type is InterfaceType) {
    variables = type.classNode.typeParameters;
    arguments = type.typeArguments;
  } else if (type is TypedefType) {
    variables = type.typedefNode.typeParameters;
    arguments = type.typeArguments;
  } else if (type is FunctionType) {
    List<TypeArgumentIssue> result = <TypeArgumentIssue>[];

    for (TypeParameter parameter in type.typeParameters) {
      result.addAll(findTypeArgumentIssues(
          parameter.bound, typeEnvironment, subtypeCheckMode,
          allowSuperBounded: true,
          isNonNullableByDefault: isNonNullableByDefault,
          areGenericArgumentsAllowed: areGenericArgumentsAllowed));
    }

    for (DartType formal in type.positionalParameters) {
      result.addAll(findTypeArgumentIssues(
          formal, typeEnvironment, subtypeCheckMode,
          allowSuperBounded: true,
          isNonNullableByDefault: isNonNullableByDefault,
          areGenericArgumentsAllowed: areGenericArgumentsAllowed));
    }

    for (NamedType named in type.namedParameters) {
      result.addAll(findTypeArgumentIssues(
          named.type, typeEnvironment, subtypeCheckMode,
          allowSuperBounded: true,
          isNonNullableByDefault: isNonNullableByDefault,
          areGenericArgumentsAllowed: areGenericArgumentsAllowed));
    }

    result.addAll(findTypeArgumentIssues(
        type.returnType, typeEnvironment, subtypeCheckMode,
        allowSuperBounded: true,
        isNonNullableByDefault: isNonNullableByDefault,
        areGenericArgumentsAllowed: areGenericArgumentsAllowed));

    return result;
  } else if (type is FutureOrType) {
    variables = typeEnvironment.coreTypes.futureClass.typeParameters;
    arguments = <DartType>[type.typeArgument];
  } else {
    return const <TypeArgumentIssue>[];
  }

  if (variables.isEmpty) {
    return typedefRhsResult.isNotEmpty
        ? typedefRhsResult
        : const <TypeArgumentIssue>[];
  }

  List<TypeArgumentIssue> result = <TypeArgumentIssue>[];
  List<TypeArgumentIssue> argumentsResult = <TypeArgumentIssue>[];

  Map<TypeParameter, DartType> substitutionMap =
      new Map<TypeParameter, DartType>.fromIterables(variables, arguments);
  for (int i = 0; i < arguments.length; ++i) {
    DartType argument = arguments[i];
    if (!areGenericArgumentsAllowed && isGenericFunctionTypeOrAlias(argument)) {
      // Generic function types aren't allowed as type arguments either.
      result.add(new TypeArgumentIssue(i, argument, variables[i], type,
          isGenericTypeAsArgumentIssue: true));
    } else if (variables[i].bound is! InvalidType) {
      DartType bound = substitute(variables[i].bound, substitutionMap);
      if (!isNonNullableByDefault) {
        bound = legacyErasure(bound);
      }
      if (!typeEnvironment.isSubtypeOf(argument, bound, subtypeCheckMode)) {
        result.add(new TypeArgumentIssue(i, argument, variables[i], type));
      }
    } else {
      // The bound is InvalidType so it's not checked, because an error was
      // reported already at the time of the creation of InvalidType.
    }

    argumentsResult.addAll(findTypeArgumentIssues(
        argument, typeEnvironment, subtypeCheckMode,
        allowSuperBounded: true,
        isNonNullableByDefault: isNonNullableByDefault,
        areGenericArgumentsAllowed: areGenericArgumentsAllowed));
  }
  result.addAll(argumentsResult);
  result.addAll(typedefRhsResult);

  // [type] is regular-bounded.
  if (result.isEmpty) return const <TypeArgumentIssue>[];
  if (!allowSuperBounded) return result;

  bool isCorrectSuperBounded = true;
  DartType? invertedType = convertSuperBoundedToRegularBounded(
      typeEnvironment, type,
      isNonNullableByDefault: isNonNullableByDefault);

  // The auxiliary type is the same as [type].  At this point we know that
  // [type] is not regular-bounded, which means that the inverted type is also
  // not regular-bounded.  These two judgments together allow us to conclude
  // that [type] is not well-bounded.
  if (invertedType == null) return result;

  if (invertedType is InterfaceType) {
    variables = invertedType.classNode.typeParameters;
    arguments = invertedType.typeArguments;
  } else if (invertedType is TypedefType) {
    variables = invertedType.typedefNode.typeParameters;
    arguments = invertedType.typeArguments;
  } else if (invertedType is FutureOrType) {
    variables = typeEnvironment.coreTypes.futureClass.typeParameters;
    arguments = <DartType>[invertedType.typeArgument];
  }
  substitutionMap =
      new Map<TypeParameter, DartType>.fromIterables(variables, arguments);
  for (int i = 0; i < arguments.length; ++i) {
    DartType argument = arguments[i];
    if (isGenericFunctionTypeOrAlias(argument)) {
      // Generic function types aren't allowed as type arguments either.
      isCorrectSuperBounded = false;
    } else if (!typeEnvironment.isSubtypeOf(argument,
        substitute(variables[i].bound, substitutionMap), subtypeCheckMode)) {
      isCorrectSuperBounded = false;
    }
  }
  if (argumentsResult.isNotEmpty) {
    isCorrectSuperBounded = false;
  }
  if (typedefRhsResult.isNotEmpty) {
    isCorrectSuperBounded = false;
  }

  // The inverted type is regular-bounded, which means that [type] is
  // well-bounded.
  if (isCorrectSuperBounded) return const <TypeArgumentIssue>[];

  // The inverted type isn't regular-bounded, but it's different from [type].
  // In this case we'll provide the programmer with the inverted type as a hint,
  // in case they were going for a super-bounded type and will benefit from that
  // information correcting the program.
  for (TypeArgumentIssue issue in result) {
    issue.invertedType = invertedType;
  }
  return result;
}

// Finds type arguments that don't follow the rules of well-boundness.
//
// [bottomType] should be either Null or Never, depending on what should be
// taken for the bottom type at the call site.  The bottom type is used in the
// checks for super-boundness for construction of the auxiliary type.  For
// details see Dart Language Specification, Section 14.3.2 The Instantiation to
// Bound Algorithm.
List<TypeArgumentIssue> findTypeArgumentIssuesForInvocation(
    List<TypeParameter> parameters,
    List<DartType> arguments,
    TypeEnvironment typeEnvironment,
    SubtypeCheckMode subtypeCheckMode,
    DartType bottomType,
    {required bool isNonNullableByDefault,
    required bool areGenericArgumentsAllowed}) {
  // ignore: unnecessary_null_comparison
  assert(isNonNullableByDefault != null);
  // ignore: unnecessary_null_comparison
  assert(areGenericArgumentsAllowed != null);

  assert(arguments.length == parameters.length);
  assert(bottomType == const NeverType.nonNullable() || bottomType is NullType);

  List<TypeArgumentIssue> result = <TypeArgumentIssue>[];
  Map<TypeParameter, DartType> substitutionMap = <TypeParameter, DartType>{};
  for (int i = 0; i < arguments.length; ++i) {
    substitutionMap[parameters[i]] = arguments[i];
  }
  for (int i = 0; i < arguments.length; ++i) {
    DartType argument = arguments[i];
    if (argument is TypeParameterType && argument.promotedBound != null) {
      // TODO(dmitryas): Consider recognizing this case with a flag on the issue
      // object.
      result.add(new TypeArgumentIssue(i, argument, parameters[i], null));
    } else if (!areGenericArgumentsAllowed &&
        isGenericFunctionTypeOrAlias(argument)) {
      // Generic function types aren't allowed as type arguments either.
      result.add(new TypeArgumentIssue(i, argument, parameters[i], null,
          isGenericTypeAsArgumentIssue: true));
    } else if (parameters[i].bound is! InvalidType) {
      DartType bound = substitute(parameters[i].bound, substitutionMap);
      if (!isNonNullableByDefault) {
        bound = legacyErasure(bound);
      }
      if (!typeEnvironment.isSubtypeOf(argument, bound, subtypeCheckMode)) {
        result.add(new TypeArgumentIssue(i, argument, parameters[i], null));
      }
    }

    result.addAll(findTypeArgumentIssues(
        argument, typeEnvironment, subtypeCheckMode,
        allowSuperBounded: true,
        isNonNullableByDefault: isNonNullableByDefault,
        areGenericArgumentsAllowed: areGenericArgumentsAllowed));
  }
  return result;
}

String getGenericTypeName(DartType type) {
  if (type is InterfaceType) {
    return type.classNode.name;
  } else if (type is TypedefType) {
    return type.typedefNode.name;
  }
  return type.toString();
}

/// Replaces all covariant occurrences of `dynamic`, `Object`, and `void` with
/// [BottomType] and all contravariant occurrences of `Null` and [BottomType]
/// with `Object`.  Returns null if the converted type is the same as [type].
DartType? convertSuperBoundedToRegularBounded(
    TypeEnvironment typeEnvironment, DartType type,
    {int variance = Variance.covariant, required bool isNonNullableByDefault}) {
  // ignore: unnecessary_null_comparison
  assert(isNonNullableByDefault != null);

  return type.accept1(
      new _SuperBoundedTypeInverter(typeEnvironment,
          isNonNullableByDefault: isNonNullableByDefault),
      variance);
}

class _SuperBoundedTypeInverter extends ReplacementVisitor {
  final TypeEnvironment typeEnvironment;
  final bool isNonNullableByDefault;

  _SuperBoundedTypeInverter(this.typeEnvironment,
      {required this.isNonNullableByDefault})
      // ignore: unnecessary_null_comparison
      : assert(typeEnvironment != null),
        // ignore: unnecessary_null_comparison
        assert(isNonNullableByDefault != null);

  bool flipTop(int variance) {
    return isNonNullableByDefault
        ? variance != Variance.contravariant
        : variance == Variance.covariant;
  }

  bool flipBottom(int variance) {
    return isNonNullableByDefault
        ? variance == Variance.contravariant
        : variance != Variance.covariant;
  }

  DartType get topType {
    return isNonNullableByDefault
        ? typeEnvironment.coreTypes.objectNullableRawType
        : const DynamicType();
  }

  DartType get bottomType {
    return isNonNullableByDefault
        ? const NeverType.nonNullable()
        : const NullType();
  }

  bool isTop(DartType node) {
    if (isNonNullableByDefault) {
      return typeEnvironment.coreTypes.isTop(node);
    } else {
      return node is DynamicType ||
          node is VoidType ||
          node is InterfaceType &&
              node.classNode == typeEnvironment.coreTypes.objectClass;
    }
  }

  bool isBottom(DartType node) {
    if (isNonNullableByDefault) {
      return typeEnvironment.coreTypes.isBottom(node);
    } else {
      return node is NullType;
    }
  }

  @override
  DartType? visitDynamicType(DynamicType node, int variance) {
    // dynamic is always a top type.
    assert(isTop(node));
    if (flipTop(variance)) {
      return bottomType;
    } else {
      return null;
    }
  }

  @override
  DartType? visitVoidType(VoidType node, int variance) {
    // void is always a top type.
    assert(isTop(node));
    if (flipTop(variance)) {
      return bottomType;
    } else {
      return null;
    }
  }

  @override
  DartType? visitInterfaceType(InterfaceType node, int variance) {
    // Check for Object-based top types.
    if (isTop(node) && flipTop(variance)) {
      return bottomType;
    } else {
      return super.visitInterfaceType(node, variance);
    }
  }

  @override
  DartType? visitFutureOrType(FutureOrType node, int variance) {
    // Check FutureOr-based top types.
    if (isTop(node) && flipTop(variance)) {
      return bottomType;
    } else {
      return super.visitFutureOrType(node, variance);
    }
  }

  @override
  DartType? visitNullType(NullType node, int variance) {
    // Null isn't a bottom type in NNBD.
    if (isBottom(node) && flipBottom(variance)) {
      return topType;
    } else {
      return null;
    }
  }

  @override
  DartType? visitNeverType(NeverType node, int variance) {
    // Depending on the variance, Never may not be a bottom type.
    if (isBottom(node) && flipBottom(variance)) {
      return topType;
    } else {
      return null;
    }
  }

  @override
  DartType? visitTypeParameterType(TypeParameterType node, int variance) {
    // Types such as X extends Never are bottom types.
    if (isBottom(node) && flipBottom(variance)) {
      return topType;
    } else {
      return null;
    }
  }

  // TypedefTypes receive special treatment because the variance of their
  // arguments' positions depend on the opt-in status of the library.
  // TODO(dmitryas): Remove the method when the discrepancy between the NNBD
  // modes is resolved.
  @override
  DartType? visitTypedefType(TypedefType node, int variance) {
    Nullability? newNullability = visitNullability(node);
    List<DartType>? newTypeArguments = null;
    for (int i = 0; i < node.typeArguments.length; i++) {
      // The implementation of instantiate-to-bound in legacy mode ignored the
      // variance of type parameters of the typedef.  This behavior is preserved
      // here in passing the 'variance' parameter unchanged in for legacy
      // libraries.
      DartType? newTypeArgument = node.typeArguments[i].accept1(
          this,
          isNonNullableByDefault
              ? Variance.combine(
                  variance, node.typedefNode.typeParameters[i].variance)
              : variance);
      if (newTypeArgument != null) {
        newTypeArguments ??= new List<DartType>.of(node.typeArguments);
        newTypeArguments[i] = newTypeArgument;
      }
    }
    return createTypedef(node, newNullability, newTypeArguments);
  }

  @override
  DartType? visitFunctionType(FunctionType node, int variance) {
    // The variance of the Typedef parameters should be taken into account only
    // when for the NNBD code.
    if (node.typedefType != null && isNonNullableByDefault) {
      return node.typedefType!.accept1(this, variance);
    } else {
      return super.visitFunctionType(node, variance);
    }
  }
}

int computeVariance(TypeParameter typeParameter, DartType type,
    {Map<TypeParameter, Map<DartType, int>>? computedVariances}) {
  computedVariances ??= new Map<TypeParameter, Map<DartType, int>>.identity();
  Map<DartType, int> variancesFromTypeParameter =
      computedVariances[typeParameter] ??= new Map<DartType, int>.identity();

  int? variance = variancesFromTypeParameter[type];
  if (variance != null) return variance;
  variancesFromTypeParameter[type] = VarianceCalculator._visitMarker;

  return variancesFromTypeParameter[type] =
      type.accept1(new VarianceCalculator(typeParameter), computedVariances);
}

class VarianceCalculator
    implements DartTypeVisitor1<int, Map<TypeParameter, Map<DartType, int>>> {
  final TypeParameter typeParameter;

  static const int _visitMarker = -2;

  VarianceCalculator(this.typeParameter);

  @override
  int defaultDartType(
      DartType node, Map<TypeParameter, Map<DartType, int>> computedVariances) {
    throw new StateError("Unhandled ${node.runtimeType} "
        "when computing variance of a type parameter.");
  }

  @override
  int visitTypeParameterType(TypeParameterType node,
      Map<TypeParameter, Map<DartType, int>> computedVariances) {
    if (node.parameter == typeParameter) return Variance.covariant;
    return Variance.unrelated;
  }

  @override
  int visitInterfaceType(InterfaceType node,
      Map<TypeParameter, Map<DartType, int>> computedVariances) {
    int result = Variance.unrelated;
    for (int i = 0; i < node.typeArguments.length; ++i) {
      result = Variance.meet(
          result,
          Variance.combine(
              node.classNode.typeParameters[i].variance,
              computeVariance(typeParameter, node.typeArguments[i],
                  computedVariances: computedVariances)));
    }
    return result;
  }

  @override
  int visitExtensionType(ExtensionType node,
      Map<TypeParameter, Map<DartType, int>> computedVariances) {
    int result = Variance.unrelated;
    for (int i = 0; i < node.typeArguments.length; ++i) {
      result = Variance.meet(
          result,
          Variance.combine(
              node.extension.typeParameters[i].variance,
              computeVariance(typeParameter, node.typeArguments[i],
                  computedVariances: computedVariances)));
    }
    return result;
  }

  @override
  int visitFutureOrType(FutureOrType node,
      Map<TypeParameter, Map<DartType, int>> computedVariances) {
    return computeVariance(typeParameter, node.typeArgument,
        computedVariances: computedVariances);
  }

  @override
  int visitTypedefType(TypedefType node,
      Map<TypeParameter, Map<DartType, int>> computedVariances) {
    int result = Variance.unrelated;
    for (int i = 0; i < node.typeArguments.length; ++i) {
      Typedef typedefNode = node.typedefNode;
      TypeParameter typedefTypeParameter = typedefNode.typeParameters[i];
      if (computedVariances.containsKey(typedefTypeParameter) &&
          computedVariances[typedefTypeParameter]![typedefNode.type] ==
              _visitMarker) {
        throw new StateError("The typedef '${node.typedefNode.name}' "
            "has a reference to itself.");
      }

      result = Variance.meet(
          result,
          Variance.combine(
              computeVariance(typeParameter, node.typeArguments[i],
                  computedVariances: computedVariances),
              computeVariance(typedefTypeParameter, typedefNode.type!,
                  computedVariances: computedVariances)));
    }
    return result;
  }

  @override
  int visitFunctionType(FunctionType node,
      Map<TypeParameter, Map<DartType, int>> computedVariances) {
    int result = Variance.unrelated;
    result = Variance.meet(
        result,
        computeVariance(typeParameter, node.returnType,
            computedVariances: computedVariances));
    for (TypeParameter functionTypeParameter in node.typeParameters) {
      // If [typeParameter] is referenced in the bound at all, it makes the
      // variance of [typeParameter] in the entire type invariant.  The
      // invocation of the visitor below is made to simply figure out if
      // [typeParameter] occurs in the bound.
      if (computeVariance(typeParameter, functionTypeParameter.bound,
              computedVariances: computedVariances) !=
          Variance.unrelated) {
        result = Variance.invariant;
      }
    }
    for (DartType positionalType in node.positionalParameters) {
      result = Variance.meet(
          result,
          Variance.combine(
              Variance.contravariant,
              computeVariance(typeParameter, positionalType,
                  computedVariances: computedVariances)));
    }
    for (NamedType namedType in node.namedParameters) {
      result = Variance.meet(
          result,
          Variance.combine(
              Variance.contravariant,
              computeVariance(typeParameter, namedType.type,
                  computedVariances: computedVariances)));
    }
    return result;
  }

  @override
  int visitNeverType(NeverType node,
      Map<TypeParameter, Map<DartType, int>> computedVariances) {
    return Variance.unrelated;
  }

  @override
  int visitNullType(
      NullType node, Map<TypeParameter, Map<DartType, int>> computedVariances) {
    return Variance.unrelated;
  }

  @override
  int visitVoidType(
      VoidType node, Map<TypeParameter, Map<DartType, int>> computedVariances) {
    return Variance.unrelated;
  }

  @override
  int visitDynamicType(DynamicType node,
      Map<TypeParameter, Map<DartType, int>> computedVariances) {
    return Variance.unrelated;
  }

  @override
  int visitInvalidType(InvalidType node,
      Map<TypeParameter, Map<DartType, int>> computedVariances) {
    return Variance.unrelated;
  }
}

bool isGenericFunctionTypeOrAlias(DartType type) {
  if (type is TypedefType) type = type.unalias;
  return type is FunctionType && type.typeParameters.isNotEmpty;
}
