// Copyright (c) 2016, 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.

library kernel.type_algebra;

import 'ast.dart';
import 'core_types.dart';
import 'src/replacement_visitor.dart';

/// Returns a type where all occurrences of the given type parameters have been
/// replaced with the corresponding types.
///
/// This will copy only the subterms of [type] that contain substituted
/// variables; all other [DartType] objects will be reused.
///
/// In particular, if no variables were substituted, this is guaranteed to
/// return the [type] instance (not a copy), so the caller may use [identical]
/// to efficiently check if a distinct type was created.
DartType substitute(DartType type, Map<TypeParameter, DartType> substitution) {
  if (substitution.isEmpty) return type;
  return Substitution.fromMap(substitution).substituteType(type);
}

/// Returns a mapping from the type parameters declared on the class of [type]
/// to the actual type arguments provided in [type].
///
/// This can be passed as argument to [substitute].
Map<TypeParameter, DartType> getSubstitutionMap(Supertype type) {
  return type.typeArguments.isEmpty
      ? const <TypeParameter, DartType>{}
      : new Map<TypeParameter, DartType>.fromIterables(
          type.classNode.typeParameters, type.typeArguments);
}

Map<TypeParameter, DartType> getUpperBoundSubstitutionMap(Class host) {
  if (host.typeParameters.isEmpty) return const <TypeParameter, DartType>{};
  Map<TypeParameter, DartType> result = <TypeParameter, DartType>{};
  for (TypeParameter parameter in host.typeParameters) {
    result[parameter] = const DynamicType();
  }
  for (TypeParameter parameter in host.typeParameters) {
    result[parameter] = substitute(parameter.bound, result);
  }
  return result;
}

/// Like [substitute], except when a type in the [substitution] map references
/// another substituted type variable, the mapping for that type is recursively
/// inserted.
///
/// For example `Set<G>` substituted with `{T -> String, G -> List<T>}` results
/// in `Set<List<String>>`.
///
/// Returns `null` if the substitution map contains a cycle reachable from a
/// type variable in [type] (the resulting type would be infinite).
///
/// The [substitution] map will be mutated so that the right-hand sides may
/// be remapped to the deeply substituted type, but only for the keys that are
/// reachable from [type].
///
/// As with [substitute], this is guaranteed to return the same instance if no
/// substitution was performed.
DartType? substituteDeep(
    DartType type, Map<TypeParameter, DartType> substitution) {
  if (substitution.isEmpty) return type;
  _DeepTypeSubstitutor substitutor = new _DeepTypeSubstitutor(substitution);
  DartType result = substitutor.visit(type);
  return substitutor.isInfinite ? null : result;
}

/// Returns true if [type] contains a reference to any of the given [variables].
///
/// [unhandledTypeHandler] is a helper function invoked on unknown implementers
/// of [DartType].  Its arguments are the unhandled type and the function that
/// can be invoked from within the handler on parts of the unknown type to
/// recursively call the visitor.  If not passed, an exception is thrown then an
/// unhandled implementer of [DartType] is encountered.
///
/// It is an error to call this with a [type] that contains a [FunctionType]
/// that declares one of the parameters in [variables].
bool containsTypeVariable(DartType type, Set<TypeParameter> variables,
    {bool Function(DartType type, bool Function(DartType type) recursor)?
        unhandledTypeHandler}) {
  if (variables.isEmpty) return false;
  return new _OccurrenceVisitor(variables,
          unhandledTypeHandler: unhandledTypeHandler)
      .visit(type);
}

/// Returns `true` if [type] contains any free type variables, that is, type
/// variable for function types whose function type is part of [type].
bool containsFreeFunctionTypeVariables(DartType type) {
  return new _FreeFunctionTypeVariableVisitor().visit(type);
}

/// Returns `true` if [type] contains any free type variables
///
/// Returns `true` if [type] contains a [TypeParameterType] that doesn't refer
/// to an enclosing generic [FunctionType] within [type].
bool containsFreeTypeVariables(DartType type,
    {Set<TypeParameter>? boundVariables}) {
  return new _FreeTypeVariableVisitor(boundVariables: boundVariables)
      .visit(type);
}

/// Generates a fresh copy of the given type parameters, with their bounds
/// substituted to reference the new parameters.
///
/// The returned object contains the fresh type parameter list as well as a
/// mapping to be used for replacing other types to use the new type parameters.
FreshTypeParameters getFreshTypeParameters(List<TypeParameter> typeParameters) {
  List<TypeParameter> freshParameters = new List<TypeParameter>.generate(
      typeParameters.length,
      (i) => new TypeParameter(typeParameters[i].name)
        ..flags = typeParameters[i].flags,
      growable: true);
  List<DartType> freshTypeArguments =
      new List<DartType>.generate(typeParameters.length, (int i) {
    return new TypeParameterType.forAlphaRenaming(
        typeParameters[i], freshParameters[i]);
  }, growable: true);
  Substitution substitution =
      Substitution.fromPairs(typeParameters, freshTypeArguments);
  for (int i = 0; i < typeParameters.length; ++i) {
    TypeParameter typeParameter = typeParameters[i];
    TypeParameter freshTypeParameter = freshParameters[i];

    freshTypeParameter.bound = substitution.substituteType(typeParameter.bound);
    freshTypeParameter.defaultType =
        substitution.substituteType(typeParameter.defaultType);
    freshTypeParameter.variance =
        typeParameter.isLegacyCovariant ? null : typeParameter.variance;
    // Annotations on a type parameter are specific to the declaration of the
    // type parameter, rather than the type parameter as such, and therefore
    // should not be copied here.
  }
  return new FreshTypeParameters(
      freshParameters, freshTypeArguments, substitution);
}

class FreshTypeParameters {
  /// The newly created type parameters.
  final List<TypeParameter> freshTypeParameters;

  /// List of [TypeParameterType]s for [TypeParameter].
  final List<DartType> freshTypeArguments;

  /// Substitution from the original type parameters to [freshTypeArguments].
  final Substitution substitution;

  FreshTypeParameters(
      this.freshTypeParameters, this.freshTypeArguments, this.substitution);

  FunctionType applyToFunctionType(FunctionType type) {
    return new FunctionType(type.positionalParameters.map(substitute).toList(),
        substitute(type.returnType), type.nullability,
        namedParameters: type.namedParameters.map(substituteNamed).toList(),
        typeParameters: freshTypeParameters,
        requiredParameterCount: type.requiredParameterCount,
        typedefType: type.typedefType == null
            ? null
            : substitute(type.typedefType!) as TypedefType);
  }

  DartType substitute(DartType type) => substitution.substituteType(type);

  NamedType substituteNamed(NamedType type) =>
      new NamedType(type.name, substitute(type.type),
          isRequired: type.isRequired);

  Supertype substituteSuper(Supertype type) {
    return substitution.substituteSupertype(type);
  }
}

// ------------------------------------------------------------------------
//                              IMPLEMENTATION
// ------------------------------------------------------------------------

abstract class Substitution {
  const Substitution();

  static const Substitution empty = _NullSubstitution.instance;

  bool get isEmpty => identical(this, empty);

  /// Substitutes each parameter to the type it maps to in [map].
  static Substitution fromMap(Map<TypeParameter, DartType> map) {
    if (map.isEmpty) return _NullSubstitution.instance;
    return new _MapSubstitution(map, map);
  }

  static Substitution filtered(Substitution sub, TypeParameterFilter filter) {
    return new _FilteredSubstitution(sub, filter);
  }

  /// Substitutes all occurrences of the given type parameters with the
  /// corresponding upper or lower bound, depending on the variance of the
  /// context where it occurs.
  ///
  /// For example the type `(T) => T` with the bounds `bottom <: T <: num`
  /// becomes `(bottom) => num` (in this example, `num` is the upper bound,
  /// and `bottom` is the lower bound).
  ///
  /// This is a way to obtain an upper bound for a type while eliminating all
  /// references to certain type variables.
  static Substitution fromUpperAndLowerBounds(
      Map<TypeParameter, DartType> upper, Map<TypeParameter, DartType> lower) {
    if (upper.isEmpty && lower.isEmpty) return _NullSubstitution.instance;
    return new _MapSubstitution(upper, lower);
  }

  /// Substitutes the type parameters on the class of [supertype] with the
  /// type arguments provided in [supertype].
  static Substitution fromSupertype(Supertype supertype) {
    if (supertype.typeArguments.isEmpty) return _NullSubstitution.instance;
    return fromMap(new Map<TypeParameter, DartType>.fromIterables(
        supertype.classNode.typeParameters, supertype.typeArguments));
  }

  /// Substitutes the type parameters on the class of [type] with the
  /// type arguments provided in [type].
  static Substitution fromInterfaceType(InterfaceType type) {
    if (type.typeArguments.isEmpty) return _NullSubstitution.instance;
    return fromMap(new Map<TypeParameter, DartType>.fromIterables(
        type.classNode.typeParameters, type.typeArguments));
  }

  /// Substitutes the type parameters on the typedef of [type] with the
  /// type arguments provided in [type].
  static Substitution fromTypedefType(TypedefType type) {
    if (type.typeArguments.isEmpty) return _NullSubstitution.instance;
    return fromMap(new Map<TypeParameter, DartType>.fromIterables(
        type.typedefNode.typeParameters, type.typeArguments));
  }

  /// Substitutes the Nth parameter in [parameters] with the Nth type in
  /// [types].
  static Substitution fromPairs(
      List<TypeParameter> parameters, List<DartType> types) {
    // TODO(asgerf): Investigate if it is more efficient to implement
    // substitution based on parallel pairwise lists instead of Maps.
    assert(parameters.length == types.length);
    if (parameters.isEmpty) return _NullSubstitution.instance;
    return fromMap(
        new Map<TypeParameter, DartType>.fromIterables(parameters, types));
  }

  /// Substitutes the type parameters on the class with bottom or dynamic,
  /// depending on the covariance of its use.
  static Substitution bottomForClass(Class class_) {
    if (class_.typeParameters.isEmpty) return _NullSubstitution.instance;
    return new _ClassBottomSubstitution(class_);
  }

  /// Substitutes covariant uses of [class_]'s type parameters with the upper
  /// bound of that type parameter.  Recursive references in the bound have
  /// been replaced by dynamic.
  static Substitution upperBoundForClass(Class class_) {
    if (class_.typeParameters.isEmpty) return _NullSubstitution.instance;
    Map<TypeParameter, DartType> upper = <TypeParameter, DartType>{};
    for (TypeParameter parameter in class_.typeParameters) {
      upper[parameter] = const DynamicType();
    }
    for (TypeParameter parameter in class_.typeParameters) {
      upper[parameter] = substitute(parameter.bound, upper);
    }
    return fromUpperAndLowerBounds(upper, {});
  }

  /// Substitutes both variables from [first] and [second], favoring those from
  /// [first] if they overlap.
  ///
  /// Neither substitution is applied to the results of the other, so this does
  /// *not* correspond to a sequence of two substitutions. For example,
  /// combining `{T -> List<G>}` with `{G -> String}` does not correspond to
  /// `{T -> List<String>}` because the result from substituting `T` is not
  /// searched for occurences of `G`.
  static Substitution combine(Substitution first, Substitution second) {
    if (first == _NullSubstitution.instance) return second;
    if (second == _NullSubstitution.instance) return first;
    return new _CombinedSubstitution(first, second);
  }

  /// Returns the substitution for [parameter]
  DartType? getSubstitute(TypeParameter parameter, bool upperBound);

  DartType substituteType(DartType node, {bool contravariant: false}) {
    return new _TopSubstitutor(this, contravariant).visit(node);
  }

  Supertype substituteSupertype(Supertype node) {
    return new _TopSubstitutor(this, false).visitSupertype(node);
  }
}

class _NullSubstitution extends Substitution {
  static const _NullSubstitution instance = const _NullSubstitution();

  const _NullSubstitution();

  @override
  DartType getSubstitute(TypeParameter parameter, bool upperBound) {
    return new TypeParameterType.forAlphaRenaming(parameter, parameter);
  }

  @override
  DartType substituteType(DartType node, {bool contravariant: false}) => node;

  @override
  Supertype substituteSupertype(Supertype node) => node;

  @override
  String toString() => "Substitution.empty";
}

class _MapSubstitution extends Substitution {
  final Map<TypeParameter, DartType> upper;
  final Map<TypeParameter, DartType> lower;

  _MapSubstitution(this.upper, this.lower);

  @override
  DartType? getSubstitute(TypeParameter parameter, bool upperBound) {
    return upperBound ? upper[parameter] : lower[parameter];
  }

  @override
  String toString() => "_MapSubstitution($upper, $lower)";
}

class _TopSubstitutor extends _TypeSubstitutor {
  final Substitution substitution;

  _TopSubstitutor(this.substitution, bool contravariant) : super(null) {
    if (contravariant) {
      invertVariance();
    }
  }

  @override
  DartType? lookup(TypeParameter parameter, bool upperBound) {
    return substitution.getSubstitute(parameter, upperBound);
  }

  @override
  TypeParameter freshTypeParameter(TypeParameter node) {
    throw 'Create a fresh environment first';
  }
}

class _ClassBottomSubstitution extends Substitution {
  final Class class_;

  _ClassBottomSubstitution(this.class_);

  @override
  DartType? getSubstitute(TypeParameter parameter, bool upperBound) {
    if (parameter.parent == class_) {
      return upperBound ? const NeverType.nonNullable() : const DynamicType();
    }
    return null;
  }
}

class _CombinedSubstitution extends Substitution {
  final Substitution first, second;

  _CombinedSubstitution(this.first, this.second);

  @override
  DartType? getSubstitute(TypeParameter parameter, bool upperBound) {
    return first.getSubstitute(parameter, upperBound) ??
        second.getSubstitute(parameter, upperBound);
  }
}

typedef bool TypeParameterFilter(TypeParameter P);

class _FilteredSubstitution extends Substitution {
  final Substitution base;
  final TypeParameterFilter filterFn;

  _FilteredSubstitution(this.base, this.filterFn);

  @override
  DartType? getSubstitute(TypeParameter parameter, bool upperBound) {
    return filterFn(parameter)
        ? base.getSubstitute(parameter, upperBound)
        : _NullSubstitution.instance.getSubstitute(parameter, upperBound);
  }
}

class _InnerTypeSubstitutor extends _TypeSubstitutor {
  final Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{};

  _InnerTypeSubstitutor(_TypeSubstitutor? outer) : super(outer);

  @override
  DartType? lookup(TypeParameter parameter, bool upperBound) {
    return substitution[parameter];
  }

  @override
  TypeParameter freshTypeParameter(TypeParameter node) {
    assert(
        !substitution.containsKey(node),
        "Function type variables cannot be substituted while still attached "
        "to the function. Perform substitution on "
        "`FunctionType.withoutTypeParameters` instead.");

    TypeParameter fresh = new TypeParameter(node.name)..flags = node.flags;
    TypeParameterType typeParameterType = substitution[node] =
        new TypeParameterType.forAlphaRenaming(node, fresh);
    fresh.bound = visit(node.bound);
    // ignore: unnecessary_null_comparison
    if (node.defaultType != null) {
      fresh.defaultType = visit(node.defaultType);
    }
    // If the bound was changed from substituting the bound we need to update
    // implicit nullability to be based on the new bound. If the bound wasn't
    // changed the computation below results in the same nullability.
    //
    // If the type variable occurred in the bound then the bound was
    // of the form `Foo<...T..>` or `FutureOr<T>` and the nullability therefore
    // has not changed.
    typeParameterType.declaredNullability =
        TypeParameterType.computeNullabilityFromBound(fresh);
    return fresh;
  }
}

/// Combines nullabilities of types during type substitution.
///
/// In a type substitution, for example, when `int` is substituted for `T` in
/// `List<T?>`, the nullability of the occurrence of the type parameter should
/// be combined with the nullability of the type that is being substituted for
/// that type parameter.  In the example above it's the nullability of `T?`
/// and `int`.  The function computes the nullability for the replacement as
/// per the following table:
///
/// |  a  \  b  |  !  |  ?  |  *  |  %  |
/// |-----------|-----|-----|-----|-----|
/// |     !     |  !  |  ?  |  *  |  !  |
/// |     ?     | N/A |  ?  |  ?  |  ?  |
/// |     *     |  *  |  ?  |  *  |  *  |
/// |     %     | N/A |  ?  |  *  |  %  |
///
/// Here `!` denotes `Nullability.nonNullable`, `?` denotes
/// `Nullability.nullable`, `*` denotes `Nullability.legacy`, and `%` denotes
/// `Nullability.undetermined`.  The table elements marked with N/A denote the
/// cases that should yield a type error before the substitution is performed.
///
/// a is nonNullable:
/// DartDocTest(
///   combineNullabilitiesForSubstitution(
///     Nullability.nonNullable, Nullability.nonNullable),
///   Nullability.nonNullable
/// )
/// DartDocTest(
///   combineNullabilitiesForSubstitution(
///     Nullability.nonNullable, Nullability.nullable),
///   Nullability.nullable
/// )
/// DartDocTest(
///   combineNullabilitiesForSubstitution(
///     Nullability.nonNullable, Nullability.legacy),
///   Nullability.legacy
/// )
/// DartDocTest(
///   combineNullabilitiesForSubstitution(
///     Nullability.nonNullable, Nullability.undetermined),
///   Nullability.nonNullable
/// )
///
/// a is nullable:
/// DartDocTest(
///   combineNullabilitiesForSubstitution(
///     Nullability.nullable, Nullability.nullable),
///   Nullability.nullable
/// )
/// DartDocTest(
///   combineNullabilitiesForSubstitution(
///     Nullability.nullable, Nullability.legacy),
///   Nullability.nullable
/// )
/// DartDocTest(
///   combineNullabilitiesForSubstitution(
///     Nullability.nullable, Nullability.undetermined),
///   Nullability.nullable
/// )
///
/// a is legacy:
/// DartDocTest(
///   combineNullabilitiesForSubstitution(
///     Nullability.legacy, Nullability.nonNullable),
///   Nullability.legacy
/// )
/// DartDocTest(
///   combineNullabilitiesForSubstitution(
///     Nullability.legacy, Nullability.nullable),
///   Nullability.nullable
/// )
/// DartDocTest(
///   combineNullabilitiesForSubstitution(
///     Nullability.legacy, Nullability.legacy),
///   Nullability.legacy
/// )
/// DartDocTest(
///   combineNullabilitiesForSubstitution(
///     Nullability.legacy, Nullability.undetermined),
///   Nullability.legacy
/// )
///
/// a is undetermined:
/// DartDocTest(
///   combineNullabilitiesForSubstitution(
///     Nullability.undetermined, Nullability.nullable),
///   Nullability.nullable
/// )
/// DartDocTest(
///   combineNullabilitiesForSubstitution(
///     Nullability.undetermined, Nullability.legacy),
///   Nullability.legacy
/// )
/// DartDocTest(
///   combineNullabilitiesForSubstitution(
///     Nullability.undetermined, Nullability.undetermined),
///   Nullability.undetermined
/// )
Nullability combineNullabilitiesForSubstitution(Nullability a, Nullability b) {
  // In the table above we may extend the function given by it, replacing N/A
  // with whatever is easier to implement.  In this implementation, we extend
  // the table function as follows:
  //
  // |  a  \  b  |  !  |  ?  |  *  |  %  |
  // |-----------|-----|-----|-----|-----|
  // |     !     |  !  |  ?  |  *  |  !  |
  // |     ?     |  ?  |  ?  |  ?  |  ?  |
  // |     *     |  *  |  ?  |  *  |  *  |
  // |     %     |  %  |  ?  |  *  |  %  |
  //

  if (a == Nullability.nullable || b == Nullability.nullable) {
    return Nullability.nullable;
  }

  if (a == Nullability.legacy || b == Nullability.legacy) {
    return Nullability.legacy;
  }

  return a;
}

abstract class _TypeSubstitutor extends DartTypeVisitor<DartType> {
  final _TypeSubstitutor? outer;
  bool covariantContext = true;

  _TypeSubstitutor(this.outer)
      : covariantContext = outer == null ? true : outer.covariantContext;

  DartType? lookup(TypeParameter parameter, bool upperBound);

  /// The number of times a variable from this environment has been used in
  /// a substitution.
  ///
  /// There is a strict requirement that we must return the same instance for
  /// types that were not altered by the substitution.  This counter lets us
  /// check quickly if anything happened in a substitution.
  int useCounter = 0;

  _InnerTypeSubstitutor newInnerEnvironment() {
    return new _InnerTypeSubstitutor(this);
  }

  void invertVariance() {
    covariantContext = !covariantContext;
  }

  Supertype visitSupertype(Supertype node) {
    if (node.typeArguments.isEmpty) return node;
    int before = useCounter;
    List<DartType> typeArguments = node.typeArguments.map(visit).toList();
    if (useCounter == before) return node;
    return new Supertype(node.classNode, typeArguments);
  }

  NamedType visitNamedType(NamedType node) {
    int before = useCounter;
    DartType type = visit(node.type);
    if (useCounter == before) return node;
    return new NamedType(node.name, type, isRequired: node.isRequired);
  }

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

  @override
  DartType defaultDartType(DartType node) => node;
  @override
  DartType visitInvalidType(InvalidType node) => node;
  @override
  DartType visitDynamicType(DynamicType node) => node;
  @override
  DartType visitVoidType(VoidType node) => node;
  @override
  DartType visitNeverType(NeverType node) => node;
  @override
  DartType visitNullType(NullType node) => node;

  @override
  DartType visitInterfaceType(InterfaceType node) {
    if (node.typeArguments.isEmpty) return node;
    int before = useCounter;
    List<DartType> typeArguments = node.typeArguments.map(visit).toList();
    if (useCounter == before) return node;
    return new InterfaceType(node.classNode, node.nullability, typeArguments);
  }

  @override
  DartType visitFutureOrType(FutureOrType node) {
    int before = useCounter;
    DartType typeArgument = node.typeArgument.accept(this);
    if (useCounter == before) return node;

    // The top-level nullability of a FutureOr should remain the same, with the
    // exception of the case of [Nullability.undetermined].  In that case it
    // remains undetermined if the nullability of [typeArgument] is
    // undetermined, and otherwise it should become [Nullability.nonNullable].
    Nullability nullability;
    if (node.declaredNullability == Nullability.undetermined) {
      if (typeArgument.nullability == Nullability.undetermined) {
        nullability = Nullability.undetermined;
      } else {
        nullability = Nullability.nonNullable;
      }
    } else {
      nullability = node.declaredNullability;
    }
    return new FutureOrType(typeArgument, nullability);
  }

  @override
  DartType visitTypedefType(TypedefType node) {
    if (node.typeArguments.isEmpty) return node;
    int before = useCounter;
    List<DartType> typeArguments = node.typeArguments.map(visit).toList();
    if (useCounter == before) return node;
    return new TypedefType(node.typedefNode, node.nullability, typeArguments);
  }

  List<TypeParameter> freshTypeParameters(List<TypeParameter> parameters) {
    if (parameters.isEmpty) return const <TypeParameter>[];
    return parameters.map(freshTypeParameter).toList();
  }

  TypeParameter freshTypeParameter(TypeParameter node);

  @override
  DartType visitFunctionType(FunctionType node) {
    // This is a bit tricky because we have to generate fresh type parameters
    // in order to change the bounds.  At the same time, if the function type
    // was unaltered, we have to return the [node] object (not a copy!).
    // Substituting a type for a fresh type variable should not be confused with
    // a "real" substitution.
    //
    // Create an inner environment to generate fresh type parameters.  The use
    // counter on the inner environment tells if the fresh type parameters have
    // any uses, but does not tell if the resulting function type is distinct.
    // Our own use counter will get incremented if something from our
    // environment has been used inside the function.
    _TypeSubstitutor inner =
        node.typeParameters.isEmpty ? this : newInnerEnvironment();
    int before = this.useCounter;
    // Invert the variance when translating parameters.
    inner.invertVariance();
    List<TypeParameter> typeParameters =
        inner.freshTypeParameters(node.typeParameters);
    List<DartType> positionalParameters = node.positionalParameters.isEmpty
        ? const <DartType>[]
        : node.positionalParameters.map(inner.visit).toList();
    List<NamedType> namedParameters = node.namedParameters.isEmpty
        ? const <NamedType>[]
        : node.namedParameters.map(inner.visitNamedType).toList();
    inner.invertVariance();
    DartType returnType = inner.visit(node.returnType);
    TypedefType? typedefType = node.typedefType == null
        ? null
        : inner.visit(node.typedefType!) as TypedefType;
    if (this.useCounter == before) return node;
    return new FunctionType(positionalParameters, returnType, node.nullability,
        namedParameters: namedParameters,
        typeParameters: typeParameters,
        requiredParameterCount: node.requiredParameterCount,
        typedefType: typedefType);
  }

  void bumpCountersUntil(_TypeSubstitutor target) {
    _TypeSubstitutor? node = this;
    while (node != target) {
      ++node!.useCounter;
      node = node.outer;
    }
    ++target.useCounter;
  }

  DartType? getSubstitute(TypeParameter variable) {
    _TypeSubstitutor? environment = this;
    while (environment != null) {
      DartType? replacement = environment.lookup(variable, covariantContext);
      if (replacement != null) {
        bumpCountersUntil(environment);
        return replacement;
      }
      environment = environment.outer;
    }
    return null;
  }

  @override
  DartType visitTypeParameterType(TypeParameterType node) {
    DartType? replacement = getSubstitute(node.parameter);
    if (replacement is InvalidType) return replacement;
    if (replacement != null) {
      return replacement.withDeclaredNullability(
          combineNullabilitiesForSubstitution(
              replacement.nullability, node.nullability));
    }
    return node;
  }
}

class _DeepTypeSubstitutor extends _InnerTypeSubstitutor {
  int depth = 0;
  bool isInfinite = false;

  _DeepTypeSubstitutor(Map<TypeParameter, DartType> substitution,
      [_DeepTypeSubstitutor? outer])
      : super(outer) {
    this.substitution.addAll(substitution);
  }

  @override
  _DeepTypeSubstitutor newInnerEnvironment() {
    return new _DeepTypeSubstitutor(<TypeParameter, DartType>{}, this);
  }

  @override
  DartType visitTypeParameterType(TypeParameterType node) {
    DartType? replacement = getSubstitute(node.parameter);
    if (replacement == null) return node;
    if (isInfinite) return replacement;
    ++depth;
    if (depth > substitution.length) {
      isInfinite = true;
      --depth;
      return replacement;
    } else {
      replacement = visit(replacement);
      // Update type to the fully fleshed-out type.
      substitution[node.parameter] = replacement;
      --depth;
      return replacement;
    }
  }
}

class _OccurrenceVisitor implements DartTypeVisitor<bool> {
  final Set<TypeParameter> variables;

  /// Helper function invoked on unknown implementers of [DartType].
  ///
  /// Its arguments are the unhandled type and the function that can be invoked
  /// from within the handler on parts of the unknown type to recursively call
  /// the visitor.  If not set, an exception is thrown then an unhandled
  /// implementer of [DartType] is encountered.
  final bool Function(DartType node, bool Function(DartType node) recursor)?
      unhandledTypeHandler;

  _OccurrenceVisitor(this.variables, {this.unhandledTypeHandler});

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

  bool visitNamedType(NamedType node) {
    return visit(node.type);
  }

  @override
  bool defaultDartType(DartType node) {
    if (unhandledTypeHandler == null) {
      throw new UnsupportedError("Unsupported type '${node.runtimeType}'.");
    } else {
      return unhandledTypeHandler!(node, visit);
    }
  }

  @override
  bool visitNeverType(NeverType node) => false;
  @override
  bool visitNullType(NullType node) => false;
  @override
  bool visitInvalidType(InvalidType node) => false;
  @override
  bool visitDynamicType(DynamicType node) => false;
  @override
  bool visitVoidType(VoidType node) => false;

  @override
  bool visitInterfaceType(InterfaceType node) {
    return node.typeArguments.any(visit);
  }

  @override
  bool visitExtensionType(ExtensionType node) {
    return node.typeArguments.any(visit);
  }

  @override
  bool visitFutureOrType(FutureOrType node) {
    return visit(node.typeArgument);
  }

  @override
  bool visitTypedefType(TypedefType node) {
    return node.typeArguments.any(visit);
  }

  @override
  bool visitFunctionType(FunctionType node) {
    return node.typeParameters.any(handleTypeParameter) ||
        node.positionalParameters.any(visit) ||
        node.namedParameters.any(visitNamedType) ||
        visit(node.returnType);
  }

  @override
  bool visitTypeParameterType(TypeParameterType node) {
    return variables.contains(node.parameter);
  }

  bool handleTypeParameter(TypeParameter node) {
    assert(!variables.contains(node));
    if (node.bound.accept(this)) return true;
    // ignore: unnecessary_null_comparison
    if (node.defaultType == null) return false;
    return node.defaultType.accept(this);
  }
}

class _FreeFunctionTypeVariableVisitor implements DartTypeVisitor<bool> {
  final Set<TypeParameter> variables = new Set<TypeParameter>();

  _FreeFunctionTypeVariableVisitor();

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

  @override
  bool defaultDartType(DartType node) {
    throw new UnsupportedError("Unsupported type $node (${node.runtimeType}.");
  }

  bool visitNamedType(NamedType node) {
    return visit(node.type);
  }

  @override
  bool visitNeverType(NeverType node) => false;
  @override
  bool visitNullType(NullType node) => false;
  @override
  bool visitInvalidType(InvalidType node) => false;
  @override
  bool visitDynamicType(DynamicType node) => false;
  @override
  bool visitVoidType(VoidType node) => false;

  @override
  bool visitInterfaceType(InterfaceType node) {
    return node.typeArguments.any(visit);
  }

  @override
  bool visitExtensionType(ExtensionType node) {
    return node.typeArguments.any(visit);
  }

  @override
  bool visitFutureOrType(FutureOrType node) {
    return visit(node.typeArgument);
  }

  @override
  bool visitTypedefType(TypedefType node) {
    return node.typeArguments.any(visit);
  }

  @override
  bool visitFunctionType(FunctionType node) {
    variables.addAll(node.typeParameters);
    bool result = node.typeParameters.any(handleTypeParameter) ||
        node.positionalParameters.any(visit) ||
        node.namedParameters.any(visitNamedType) ||
        visit(node.returnType);
    variables.removeAll(node.typeParameters);
    return result;
  }

  @override
  bool visitTypeParameterType(TypeParameterType node) {
    return node.parameter.parent == null && !variables.contains(node.parameter);
  }

  bool handleTypeParameter(TypeParameter node) {
    assert(variables.contains(node));
    if (node.bound.accept(this)) return true;
    // ignore: unnecessary_null_comparison
    if (node.defaultType == null) return false;
    return node.defaultType.accept(this);
  }
}

class _FreeTypeVariableVisitor implements DartTypeVisitor<bool> {
  final Set<TypeParameter> boundVariables;

  _FreeTypeVariableVisitor({Set<TypeParameter>? boundVariables})
      : this.boundVariables = boundVariables ?? <TypeParameter>{};

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

  @override
  bool defaultDartType(DartType node) {
    throw new UnsupportedError("Unsupported type $node (${node.runtimeType}.");
  }

  bool visitNamedType(NamedType node) {
    return visit(node.type);
  }

  @override
  bool visitNeverType(NeverType node) => false;
  @override
  bool visitNullType(NullType node) => false;
  @override
  bool visitInvalidType(InvalidType node) => false;
  @override
  bool visitDynamicType(DynamicType node) => false;
  @override
  bool visitVoidType(VoidType node) => false;

  @override
  bool visitInterfaceType(InterfaceType node) {
    return node.typeArguments.any(visit);
  }

  @override
  bool visitExtensionType(ExtensionType node) {
    return node.typeArguments.any(visit);
  }

  @override
  bool visitFutureOrType(FutureOrType node) {
    return visit(node.typeArgument);
  }

  @override
  bool visitTypedefType(TypedefType node) {
    return node.typeArguments.any(visit);
  }

  @override
  bool visitFunctionType(FunctionType node) {
    boundVariables.addAll(node.typeParameters);
    bool result = node.typeParameters.any(handleTypeParameter) ||
        node.positionalParameters.any(visit) ||
        node.namedParameters.any(visitNamedType) ||
        visit(node.returnType);
    boundVariables.removeAll(node.typeParameters);
    return result;
  }

  @override
  bool visitTypeParameterType(TypeParameterType node) {
    return !boundVariables.contains(node.parameter);
  }

  bool handleTypeParameter(TypeParameter node) {
    assert(boundVariables.contains(node));
    if (node.bound.accept(this)) return true;
    // ignore: unnecessary_null_comparison
    if (node.defaultType == null) return false;
    return node.defaultType.accept(this);
  }
}

Nullability uniteNullabilities(Nullability a, Nullability b) {
  if (a == Nullability.nullable || b == Nullability.nullable) {
    return Nullability.nullable;
  }
  if (a == Nullability.legacy || b == Nullability.legacy) {
    return Nullability.legacy;
  }
  if (a == Nullability.undetermined || b == Nullability.undetermined) {
    return Nullability.undetermined;
  }
  return Nullability.nonNullable;
}

Nullability intersectNullabilities(Nullability a, Nullability b) {
  if (a == Nullability.nonNullable || b == Nullability.nonNullable) {
    return Nullability.nonNullable;
  }
  if (a == Nullability.undetermined || b == Nullability.undetermined) {
    return Nullability.undetermined;
  }
  if (a == Nullability.legacy || b == Nullability.legacy) {
    return Nullability.legacy;
  }
  return Nullability.nullable;
}

/// Tells if a [DartType] is primitive or not.
///
/// This is useful in recursive algorithms over types where the primitive types
/// are the base cases of the recursion.  According to the visitor a primitive
/// type is any [DartType] that doesn't include other [DartType]s as its parts.
/// The nullability attributes don't affect the primitiveness of a type.
bool isPrimitiveDartType(DartType type) {
  return type.accept(const _PrimitiveTypeVerifier());
}

/// Visitors that implements the algorithm of [isPrimitiveDartType].
///
/// The visitor is shallow, that is, it doesn't recurse over the given type due
/// to its purpose.  The reason for having a visitor is to make the need for an
/// update visible when a new implementer of [DartType] is introduced in Kernel.
class _PrimitiveTypeVerifier implements DartTypeVisitor<bool> {
  const _PrimitiveTypeVerifier();

  @override
  bool defaultDartType(DartType node) {
    throw new UnsupportedError(
        "Unsupported operation: _PrimitiveTypeVerifier(${node.runtimeType})");
  }

  @override
  bool visitDynamicType(DynamicType node) => true;

  @override
  bool visitFunctionType(FunctionType node) {
    // Function types are never primitive because they at least include the
    // return types as their parts.
    return false;
  }

  @override
  bool visitFutureOrType(FutureOrType node) => false;

  @override
  bool visitInterfaceType(InterfaceType node) {
    return node.typeArguments.isEmpty;
  }

  @override
  bool visitExtensionType(ExtensionType node) {
    return node.typeArguments.isEmpty;
  }

  @override
  bool visitInvalidType(InvalidType node) {
    throw new UnsupportedError(
        "Unsupported operation: _PrimitiveTypeVerifier(InvalidType).");
  }

  @override
  bool visitNeverType(NeverType node) => true;

  @override
  bool visitNullType(NullType node) => true;

  @override
  bool visitTypeParameterType(TypeParameterType node) {
    return node.promotedBound == null;
  }

  @override
  bool visitTypedefType(TypedefType node) {
    return node.typeArguments.isEmpty;
  }

  @override
  bool visitVoidType(VoidType node) => true;
}

/// Removes the application of ? or * from the type.
///
/// Some types are nullable even without the application of the nullable type
/// constructor at the top level, for example, Null or FutureOr<int?>.
// TODO(cstefantsova): Remove [coreTypes] parameter when NullType is landed.
DartType unwrapNullabilityConstructor(DartType type, CoreTypes coreTypes) {
  return type.accept1(const _NullabilityConstructorUnwrapper(), coreTypes);
}

/// Implementation of [unwrapNullabilityConstructor] as a visitor.
///
/// Implementing the function as a visitor makes the necessity of supporting a
/// new implementation of [DartType] visible at compile time.
// TODO(cstefantsova): Remove CoreTypes as the second argument when NullType is
// landed.
class _NullabilityConstructorUnwrapper
    implements DartTypeVisitor1<DartType, CoreTypes> {
  const _NullabilityConstructorUnwrapper();

  @override
  DartType defaultDartType(DartType node, CoreTypes coreTypes) {
    throw new UnsupportedError("Unsupported operation: "
        "_NullabilityConstructorUnwrapper(${node.runtimeType})");
  }

  @override
  DartType visitDynamicType(DynamicType node, CoreTypes coreTypes) => node;

  @override
  DartType visitFunctionType(FunctionType node, CoreTypes coreTypes) {
    return node.withDeclaredNullability(Nullability.nonNullable);
  }

  @override
  DartType visitFutureOrType(FutureOrType node, CoreTypes coreTypes) {
    return node.withDeclaredNullability(Nullability.nonNullable);
  }

  @override
  DartType visitInterfaceType(InterfaceType node, CoreTypes coreTypes) {
    return node.withDeclaredNullability(Nullability.nonNullable);
  }

  @override
  DartType visitExtensionType(ExtensionType node, CoreTypes coreTypes) {
    return node.withDeclaredNullability(Nullability.nonNullable);
  }

  @override
  DartType visitInvalidType(InvalidType node, CoreTypes coreTypes) => node;

  @override
  DartType visitNeverType(NeverType node, CoreTypes coreTypes) {
    return node.withDeclaredNullability(Nullability.nonNullable);
  }

  @override
  DartType visitNullType(NullType node, CoreTypes coreTypes) => node;

  @override
  DartType visitTypeParameterType(TypeParameterType node, CoreTypes coreTypes) {
    if (node.promotedBound != null) {
      // Intersection types don't have their own nullabilities.
      return node;
    } else {
      return node.withDeclaredNullability(
          TypeParameterType.computeNullabilityFromBound(node.parameter));
    }
  }

  @override
  DartType visitTypedefType(TypedefType node, CoreTypes coreTypes) {
    return node.withDeclaredNullability(Nullability.nonNullable);
  }

  @override
  DartType visitVoidType(VoidType node, CoreTypes coreTypes) => node;
}

abstract class NullabilityAwareTypeVariableEliminatorBase
    extends ReplacementVisitor {
  final DartType bottomType;
  final DartType topType;
  final DartType topFunctionType;
  late bool _isLeastClosure;

  NullabilityAwareTypeVariableEliminatorBase(
      {required this.bottomType,
      required this.topType,
      required this.topFunctionType})
      :
        // ignore: unnecessary_null_comparison
        assert(bottomType != null),
        // ignore: unnecessary_null_comparison
        assert(topType != null),
        // ignore: unnecessary_null_comparison
        assert(topFunctionType != null);

  bool containsTypeVariablesToEliminate(DartType type);

  bool isTypeVariableToEliminate(TypeParameter typeParameter);

  /// Returns a subtype of [type] for all variables to be eliminated.
  DartType eliminateToLeast(DartType type) {
    _isLeastClosure = true;
    return type.accept1(this, Variance.covariant) ?? type;
  }

  /// Returns a supertype of [type] for all variables to be eliminated.
  DartType eliminateToGreatest(DartType type) {
    _isLeastClosure = false;
    return type.accept1(this, Variance.covariant) ?? type;
  }

  DartType getTypeParameterReplacement(int variance) {
    bool isCovariant = variance == Variance.covariant;
    return _isLeastClosure && isCovariant || (!_isLeastClosure && !isCovariant)
        ? bottomType
        : topType;
  }

  DartType getFunctionReplacement(int variance) {
    bool isCovariant = variance == Variance.covariant;
    return _isLeastClosure && isCovariant || (!_isLeastClosure && !isCovariant)
        ? bottomType
        : topFunctionType;
  }

  @override
  DartType? visitFunctionType(FunctionType node, int variance) {
    // - if `S` is
    //   `T Function<X0 extends B0, ...., Xk extends Bk>(T0 x0, ...., Tn xn,
    //       [Tn+1 xn+1, ..., Tm xm])`
    //   or `T Function<X0 extends B0, ...., Xk extends Bk>(T0 x0, ...., Tn xn,
    //       {Tn+1 xn+1, ..., Tm xm})`
    //   and `L` contains any free type variables from any of the `Bi`:
    //  - The least closure of `S` with respect to `L` is `Never`
    //  - The greatest closure of `S` with respect to `L` is `Function`
    if (node.typeParameters.isNotEmpty) {
      for (TypeParameter typeParameter in node.typeParameters) {
        if (containsTypeVariablesToEliminate(typeParameter.bound)) {
          return getFunctionReplacement(variance);
        }
      }
    }
    return super.visitFunctionType(node, variance);
  }

  @override
  DartType? visitTypeParameterType(TypeParameterType node, int variance) {
    if (isTypeVariableToEliminate(node.parameter)) {
      return getTypeParameterReplacement(variance);
    }
    return super.visitTypeParameterType(node, variance);
  }
}

/// Eliminates specified free type parameters in a type.
///
/// Use this class when only a specific subset of unbound variables in a type
/// should be substituted with one of [bottomType], [topType], or
/// [topFunctionType].  For example, running a
/// `NullabilityAwareTypeVariableEliminatorBase({T}, Never, Object?,
/// Function).eliminateToLeast` on type `T Function<S>(S s, R r)` will return
/// `Never Function<S>(S s, R r)`.
///
/// The algorithm for elimination of type variables is described in
/// https://github.com/dart-lang/language/pull/957
class NullabilityAwareTypeVariableEliminator
    extends NullabilityAwareTypeVariableEliminatorBase {
  final Set<TypeParameter> eliminationTargets;
  final bool Function(DartType type, bool Function(DartType type) recursor)?
      unhandledTypeHandler;

  NullabilityAwareTypeVariableEliminator(
      {required this.eliminationTargets,
      required DartType bottomType,
      required DartType topType,
      required DartType topFunctionType,
      this.unhandledTypeHandler})
      // ignore: unnecessary_null_comparison
      : assert(eliminationTargets != null),
        // ignore: unnecessary_null_comparison
        assert(bottomType != null),
        // ignore: unnecessary_null_comparison
        assert(topType != null),
        // ignore: unnecessary_null_comparison
        assert(topFunctionType != null),
        super(
            bottomType: bottomType,
            topType: topType,
            topFunctionType: topFunctionType);

  @override
  bool containsTypeVariablesToEliminate(DartType type) {
    return containsTypeVariable(type, eliminationTargets,
        unhandledTypeHandler: unhandledTypeHandler);
  }

  @override
  bool isTypeVariableToEliminate(TypeParameter typeParameter) {
    return eliminationTargets.contains(typeParameter);
  }
}

/// Eliminates all free type parameters in a type.
///
/// Use this class when all unbound variables in a type should be substituted
/// with one of [bottomType], [topType], or [topFunctionType].  For example,
/// running a `NullabilityAwareFreeTypeVariableEliminator(Never, Object?,
/// Function).eliminateToLeast` on type `T Function<S>(S s, R r)` will return
/// `Never Function<S>(S s, Object? r)`.
///
/// The algorithm for elimination of type variables is described in
/// https://github.com/dart-lang/language/pull/957
class NullabilityAwareFreeTypeVariableEliminator
    extends NullabilityAwareTypeVariableEliminatorBase {
  Set<TypeParameter> _boundVariables = <TypeParameter>{};

  NullabilityAwareFreeTypeVariableEliminator(
      {required DartType bottomType,
      required DartType topType,
      required DartType topFunctionType})
      :
        // ignore: unnecessary_null_comparison
        assert(bottomType != null),
        // ignore: unnecessary_null_comparison
        assert(topType != null),
        // ignore: unnecessary_null_comparison
        assert(topFunctionType != null),
        super(
            bottomType: bottomType,
            topType: topType,
            topFunctionType: topFunctionType);

  @override
  DartType? visitFunctionType(FunctionType node, int variance) {
    if (node.typeParameters.isNotEmpty) {
      _boundVariables.addAll(node.typeParameters);
      DartType? result = super.visitFunctionType(node, variance);
      _boundVariables.removeAll(node.typeParameters);
      return result;
    } else {
      return super.visitFunctionType(node, variance);
    }
  }

  @override
  bool containsTypeVariablesToEliminate(DartType type) {
    return containsFreeTypeVariables(type, boundVariables: _boundVariables);
  }

  @override
  bool isTypeVariableToEliminate(TypeParameter typeParameter) {
    return !_boundVariables.contains(typeParameter);
  }
}

/// Computes [type] as if declared without nullability markers.
///
/// For example, int? and int* are considered applications of the nullable and
/// the legacy type constructors to type int correspondingly.
/// [computeTypeWithoutNullabilityMarker] peels off these type constructors,
/// returning the non-nullable version of type int.  In case of
/// [TypeParameterType]s, the result may be either [Nullability.nonNullable] or
/// [Nullability.undetermined], depending on the bound.
DartType computeTypeWithoutNullabilityMarker(DartType type,
    {required bool isNonNullableByDefault}) {
  // ignore: unnecessary_null_comparison
  assert(isNonNullableByDefault != null);

  if (type is TypeParameterType) {
    if (type.promotedBound == null) {
      // The default nullability for library is used when there are no
      // nullability markers on the type.
      return new TypeParameterType(
          type.parameter,
          _defaultNullabilityForTypeParameterType(type.parameter,
              isNonNullableByDefault: isNonNullableByDefault));
    } else {
      // Intersection types can't be arguments to the nullable and the legacy
      // type constructors, so nothing can be peeled off.
      return type;
    }
  } else if (type is NullType) {
    return type;
  } else {
    // For most types, peeling off the nullability constructors means that
    // they become non-nullable.
    return type.withDeclaredNullability(Nullability.nonNullable);
  }
}

/// Returns true if [type] is declared without nullability markers.
///
/// An example of the nullable type constructor application is T? where T is a
/// type parameter.  Some examples of types declared without nullability markers
/// are T% and S, where T and S are type parameters such that T extends Object?
/// and S extends Object.
bool isTypeParameterTypeWithoutNullabilityMarker(TypeParameterType type,
    {required bool isNonNullableByDefault}) {
  // ignore: unnecessary_null_comparison
  assert(isNonNullableByDefault != null);

  // The default nullability for library is used when there are no nullability
  // markers on the type.
  return type.promotedBound == null &&
      type.declaredNullability ==
          _defaultNullabilityForTypeParameterType(type.parameter,
              isNonNullableByDefault: isNonNullableByDefault);
}

bool isTypeWithoutNullabilityMarker(DartType type,
    {required bool isNonNullableByDefault}) {
  // ignore: unnecessary_null_comparison
  assert(isNonNullableByDefault != null);
  return !type.accept(new _NullabilityMarkerDetector(isNonNullableByDefault));
}

class _NullabilityMarkerDetector implements DartTypeVisitor<bool> {
  final bool isNonNullableByDefault;

  const _NullabilityMarkerDetector(this.isNonNullableByDefault);

  @override
  bool defaultDartType(DartType node) {
    throw new UnsupportedError("Unsupported operation: "
        "_NullabilityMarkerDetector(${node.runtimeType})");
  }

  @override
  bool visitDynamicType(DynamicType node) => false;

  @override
  bool visitFunctionType(FunctionType node) {
    assert(node.declaredNullability != Nullability.undetermined);
    return node.declaredNullability == Nullability.nullable ||
        node.declaredNullability == Nullability.legacy;
  }

  @override
  bool visitFutureOrType(FutureOrType node) {
    if (node.declaredNullability == Nullability.nullable ||
        node.declaredNullability == Nullability.legacy) {
      return true;
    }
    return false;
  }

  @override
  bool visitInterfaceType(InterfaceType node) {
    assert(node.declaredNullability != Nullability.undetermined);
    return node.declaredNullability == Nullability.nullable ||
        node.declaredNullability == Nullability.legacy;
  }

  @override
  bool visitExtensionType(ExtensionType node) {
    assert(node.declaredNullability != Nullability.undetermined);
    return node.declaredNullability == Nullability.nullable ||
        node.declaredNullability == Nullability.legacy;
  }

  @override
  bool visitInvalidType(InvalidType node) => false;

  @override
  bool visitNeverType(NeverType node) {
    assert(node.declaredNullability != Nullability.undetermined);
    return node.declaredNullability == Nullability.nullable ||
        node.declaredNullability == Nullability.legacy;
  }

  @override
  bool visitNullType(NullType node) => false;

  @override
  bool visitTypeParameterType(TypeParameterType node) {
    return !isTypeParameterTypeWithoutNullabilityMarker(node,
        isNonNullableByDefault: isNonNullableByDefault);
  }

  @override
  bool visitTypedefType(TypedefType node) {
    assert(node.declaredNullability != Nullability.undetermined);
    return node.declaredNullability == Nullability.nullable ||
        node.declaredNullability == Nullability.legacy;
  }

  @override
  bool visitVoidType(VoidType node) => false;
}

/// Returns true if [type] is an application of the nullable type constructor.
///
/// A type is considered an application of the nullable type constructor if it
/// was declared with the ? marker.  Some examples of such types are int?,
/// String?, Object?, and T? where T is a type parameter.  Types dynamic, void,
/// and Null are nullable, but aren't considered applications of the nullable
/// type constructor.
bool isNullableTypeConstructorApplication(DartType type) {
  if (type is TypeParameterType && type.promotedBound != null) {
    // Promoted types are never considered applications of ?.
    return false;
  }
  return type.declaredNullability == Nullability.nullable &&
      type is! DynamicType &&
      type is! VoidType &&
      type is! NullType;
}

/// Returns true if [type] is an application of the legacy type constructor.
///
/// A type is considered an application of the legacy type constructor if it was
/// declared within a legacy library and is not one of exempt types, such as
/// dynamic or void.
bool isLegacyTypeConstructorApplication(DartType type,
    {required bool isNonNullableByDefault}) {
  // ignore: unnecessary_null_comparison
  assert(isNonNullableByDefault != null);

  if (type is TypeParameterType) {
    // The legacy nullability is considered an application of the legacy
    // nullability constructor if it doesn't match the default nullability
    // of the type-parameter type for the library.
    return type.declaredNullability == Nullability.legacy &&
        !isTypeParameterTypeWithoutNullabilityMarker(type,
            isNonNullableByDefault: isNonNullableByDefault);
  } else if (type is InvalidType) {
    return false;
  } else {
    return type.declaredNullability == Nullability.legacy;
  }
}

Nullability _defaultNullabilityForTypeParameterType(TypeParameter parameter,
    {required bool isNonNullableByDefault}) {
  // ignore: unnecessary_null_comparison
  assert(isNonNullableByDefault != null);
  return isNonNullableByDefault
      ? TypeParameterType.computeNullabilityFromBound(parameter)
      : Nullability.legacy;
}

/// Recalculates and updates nullabilities of the bounds in [typeParameters].
///
/// The procedure is intended to be used on type parameters that are in the
/// scope of another declaration with type parameters. After a substitution
/// involving the outer type parameters is performed, some potentially nullable
/// bounds of the inner parameters can change to non-nullable. Since type
/// parameters can depend on each other, the occurrences of those with changed
/// nullabilities need to be updated in the bounds of the entire type parameter
/// set.
void updateBoundNullabilities(List<TypeParameter> typeParameters) {
  if (typeParameters.isEmpty) return;
  List<bool> visited =
      new List<bool>.filled(typeParameters.length, false, growable: false);
  for (int parameterIndex = 0;
      parameterIndex < typeParameters.length;
      parameterIndex++) {
    _updateBoundNullabilities(typeParameters, visited, parameterIndex);
  }
}

void _updateBoundNullabilities(
    List<TypeParameter> typeParameters, List<bool> visited, int startIndex) {
  if (visited[startIndex]) return;
  visited[startIndex] = true;

  TypeParameter parameter = typeParameters[startIndex];
  DartType bound = parameter.bound;
  while (bound is FutureOrType) {
    bound = bound.typeArgument;
  }
  if (bound is TypeParameterType) {
    int nextIndex = typeParameters.indexOf(bound.parameter);
    if (nextIndex != -1) {
      _updateBoundNullabilities(typeParameters, visited, nextIndex);
      Nullability updatedNullability =
          TypeParameterType.computeNullabilityFromBound(
              typeParameters[nextIndex]);
      if (bound.declaredNullability != updatedNullability) {
        parameter.bound = _updateNestedFutureOrNullability(
            parameter.bound, updatedNullability);
      }
    }
  }
}

DartType _updateNestedFutureOrNullability(
    DartType typeToUpdate, Nullability updatedNullability) {
  if (typeToUpdate is FutureOrType) {
    return new FutureOrType(
        _updateNestedFutureOrNullability(
            typeToUpdate.typeArgument, updatedNullability),
        typeToUpdate.declaredNullability);
  } else {
    return typeToUpdate.withDeclaredNullability(updatedNullability);
  }
}
