// 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_environment;

import 'ast.dart';
import 'class_hierarchy.dart';
import 'core_types.dart';
import 'type_algebra.dart';

import 'src/hierarchy_based_type_environment.dart'
    show HierarchyBasedTypeEnvironment;
import 'src/types.dart';

typedef void ErrorHandler(TreeNode node, String message);

abstract class TypeEnvironment extends Types {
  @override
  final CoreTypes coreTypes;

  TypeEnvironment.fromSubclass(this.coreTypes, ClassHierarchyBase base)
      : super(base);

  factory TypeEnvironment(CoreTypes coreTypes, ClassHierarchy hierarchy) {
    return new HierarchyBasedTypeEnvironment(coreTypes, hierarchy);
  }

  Class get intClass => coreTypes.intClass;
  Class get numClass => coreTypes.numClass;
  Class get functionClass => coreTypes.functionClass;
  Class get objectClass => coreTypes.objectClass;

  InterfaceType get objectLegacyRawType => coreTypes.objectLegacyRawType;
  InterfaceType get objectNullableRawType => coreTypes.objectNullableRawType;
  InterfaceType get functionLegacyRawType => coreTypes.functionLegacyRawType;

  /// Returns the type `List<E>` with the given [nullability] and [elementType]
  /// as `E`.
  InterfaceType listType(DartType elementType, Nullability nullability) {
    return new InterfaceType(
        coreTypes.listClass, nullability, <DartType>[elementType]);
  }

  /// Returns the type `Set<E>` with the given [nullability] and [elementType]
  /// as `E`.
  InterfaceType setType(DartType elementType, Nullability nullability) {
    return new InterfaceType(
        coreTypes.setClass, nullability, <DartType>[elementType]);
  }

  /// Returns the type `Map<K,V>` with the given [nullability], [key] as `K`
  /// and [value] is `V`.
  InterfaceType mapType(DartType key, DartType value, Nullability nullability) {
    return new InterfaceType(
        coreTypes.mapClass, nullability, <DartType>[key, value]);
  }

  /// Returns the type `Iterable<E>` with the given [nullability] and [type]
  /// as `E`.
  InterfaceType iterableType(DartType type, Nullability nullability) {
    return new InterfaceType(
        coreTypes.iterableClass, nullability, <DartType>[type]);
  }

  /// Returns the type `Stream<E>` with the given [nullability] and [type]
  /// as `E`.
  InterfaceType streamType(DartType type, Nullability nullability) {
    return new InterfaceType(
        coreTypes.streamClass, nullability, <DartType>[type]);
  }

  /// Returns the type `Future<E>` with the given [nullability] and [type]
  /// as `E`.
  InterfaceType futureType(DartType type, Nullability nullability) {
    return new InterfaceType(
        coreTypes.futureClass, nullability, <DartType>[type]);
  }

  DartType _withDeclaredNullability(DartType type, Nullability nullability) {
    if (type is NullType) return type;
    return type.withDeclaredNullability(
        uniteNullabilities(type.declaredNullability, nullability));
  }

  /// Returns the `flatten` of [type] as defined in the spec, which unwraps a
  /// layer of Future or FutureOr from a type.
  DartType flatten(DartType t) {
    // if T is S? then flatten(T) = flatten(S)?
    // otherwise if T is S* then flatten(T) = flatten(S)*
    // -- this is preserve with the calls to [_withDeclaredNullability] below.

    // otherwise if T is FutureOr<S> then flatten(T) = S
    if (t is FutureOrType) {
      return _withDeclaredNullability(t.typeArgument, t.declaredNullability);
    }

    // otherwise if T <: Future then let S be a type such that T <: Future<S>
    //   and for all R, if T <: Future<R> then S <: R; then flatten(T) = S
    DartType resolved = _resolveTypeParameterType(t);
    if (resolved is InterfaceType) {
      List<DartType>? futureArguments =
          getTypeArgumentsAsInstanceOf(resolved, coreTypes.futureClass);
      if (futureArguments != null) {
        return _withDeclaredNullability(futureArguments.single, t.nullability);
      }
    }

    // otherwise flatten(T) = T
    return t;
  }

  /// Returns the non-type parameter type bound of [type].
  DartType _resolveTypeParameterType(DartType type) {
    while (type is TypeParameterType) {
      TypeParameterType typeParameterType = type;
      type = typeParameterType.bound;
    }
    return type;
  }

  /// Returns the type of the element in the for-in statement [node] with
  /// [iterableExpressionType] as the static type of the iterable expression.
  ///
  /// The [iterableExpressionType] must be a subclass of `Stream` or `Iterable`
  /// depending on whether `node.isAsync` is `true` or not.
  DartType forInElementType(
      ForInStatement node, DartType iterableExpressionType) {
    // TODO(johnniwinther): Update this to use the type of
    //  `iterable.iterator.current` if inference is updated accordingly.
    InterfaceType iterableType =
        _resolveTypeParameterType(iterableExpressionType) as InterfaceType;
    if (node.isAsync) {
      List<DartType>? typeArguments =
          getTypeArgumentsAsInstanceOf(iterableType, coreTypes.streamClass);
      return typeArguments!.single;
    } else {
      List<DartType>? typeArguments =
          getTypeArgumentsAsInstanceOf(iterableType, coreTypes.iterableClass);
      return typeArguments!.single;
    }
  }

  /// True if [member] is a binary operator whose return type is defined by
  /// the both operand types.
  bool isSpecialCasedBinaryOperator(Procedure member,
      {bool isNonNullableByDefault: false}) {
    if (isNonNullableByDefault) {
      Class? class_ = member.enclosingClass;
      // TODO(johnniwinther): Do we need to recognize backend implementation
      //  methods?
      if (class_ == coreTypes.intClass ||
          class_ == coreTypes.numClass ||
          class_ == coreTypes.doubleClass) {
        String name = member.name.text;
        return name == '+' ||
            name == '-' ||
            name == '*' ||
            name == 'remainder' ||
            name == '%';
      }
    } else {
      Class? class_ = member.enclosingClass;
      if (class_ == coreTypes.intClass || class_ == coreTypes.numClass) {
        String name = member.name.text;
        return name == '+' ||
            name == '-' ||
            name == '*' ||
            name == 'remainder' ||
            name == '%';
      }
    }
    return false;
  }

  /// True if [member] is a ternary operator whose return type is defined by
  /// the least upper bound of the operand types.
  bool isSpecialCasedTernaryOperator(Procedure member,
      {bool isNonNullableByDefault: false}) {
    if (isNonNullableByDefault) {
      Class? class_ = member.enclosingClass;
      if (class_ == coreTypes.intClass || class_ == coreTypes.numClass) {
        String name = member.name.text;
        return name == 'clamp';
      }
    }
    return false;
  }

  /// Returns the static return type of a special cased binary operator
  /// (see [isSpecialCasedBinaryOperator]) given the static type of the
  /// operands.
  DartType getTypeOfSpecialCasedBinaryOperator(DartType type1, DartType type2,
      {bool isNonNullableByDefault: false}) {
    if (isNonNullableByDefault) {
      // Let e be an expression of one of the forms e1 + e2, e1 - e2, e1 * e2,
      // e1 % e2 or e1.remainder(e2), where the static type of e1 is a non-Never
      // type T and T <: num, and where the static type of e2 is S and S is
      // assignable to num. Then:
      if (type1 is! NeverType &&
              isSubtypeOf(type1, coreTypes.numNonNullableRawType,
                  SubtypeCheckMode.withNullabilities) &&
              type2 is DynamicType ||
          isSubtypeOf(type2, coreTypes.numNonNullableRawType,
              SubtypeCheckMode.withNullabilities)) {
        if (isSubtypeOf(type1, coreTypes.doubleNonNullableRawType,
            SubtypeCheckMode.withNullabilities)) {
          // If T <: double then the static type of e is double. This includes S
          // being dynamic or Never.
          return coreTypes.doubleNonNullableRawType;
        } else if (type2 is! NeverType &&
            isSubtypeOf(type2, coreTypes.doubleNonNullableRawType,
                SubtypeCheckMode.withNullabilities)) {
          // If S <: double and not S <:Never, then the static type of e is
          // double.
          return coreTypes.doubleNonNullableRawType;
        } else if (isSubtypeOf(type1, coreTypes.intNonNullableRawType,
                SubtypeCheckMode.withNullabilities) &&
            type2 is! NeverType &&
            isSubtypeOf(type2, coreTypes.intNonNullableRawType,
                SubtypeCheckMode.withNullabilities)) {
          // If T <: int , S <: int and not S <: Never, then the static type of
          // e is int.
          return coreTypes.intNonNullableRawType;
        } else if (type2 is! NeverType &&
            isSubtypeOf(type2, type1, SubtypeCheckMode.withNullabilities)) {
          // Otherwise the static type of e is num.
          return coreTypes.numNonNullableRawType;
        }
      }
      // Otherwise the static type of e is num.
      return coreTypes.numNonNullableRawType;
    } else {
      type1 = _resolveTypeParameterType(type1);
      type2 = _resolveTypeParameterType(type2);

      if (type1 == type2) return type1;

      if (type1 is InterfaceType && type2 is InterfaceType) {
        if (type1.classNode == type2.classNode) {
          return type1;
        }
        if (type1.classNode == coreTypes.doubleClass ||
            type2.classNode == coreTypes.doubleClass) {
          return coreTypes.doubleRawType(type1.nullability);
        }
      }

      return coreTypes.numRawType(type1.nullability);
    }
  }

  DartType getTypeOfSpecialCasedTernaryOperator(
      DartType type1, DartType type2, DartType type3, Library clientLibrary) {
    if (clientLibrary.isNonNullableByDefault) {
      // Let e be a normal invocation of the form e1.clamp(e2, e3), where the
      // static types of e1, e2 and e3 are T1, T2 and T3 respectively, and where
      // T1, T2, and T3 are all non-Never subtypes of num. Then:
      if (type1 is! NeverType && type2 is! NeverType && type3 is! NeverType
          /* We skip the check that all types are subtypes of num because, if
          not, we'll compute the static type to be num, anyway.*/
          ) {
        if (isSubtypeOf(type1, coreTypes.intNonNullableRawType,
                SubtypeCheckMode.withNullabilities) &&
            isSubtypeOf(type2, coreTypes.intNonNullableRawType,
                SubtypeCheckMode.withNullabilities) &&
            isSubtypeOf(type3, coreTypes.intNonNullableRawType,
                SubtypeCheckMode.withNullabilities)) {
          // If T1, T2 and T3 are all subtypes of int, the static type of e is
          // int.
          return coreTypes.intNonNullableRawType;
        } else if (isSubtypeOf(type1, coreTypes.doubleNonNullableRawType,
                SubtypeCheckMode.withNullabilities) &&
            isSubtypeOf(type2, coreTypes.doubleNonNullableRawType,
                SubtypeCheckMode.withNullabilities) &&
            isSubtypeOf(type3, coreTypes.doubleNonNullableRawType,
                SubtypeCheckMode.withNullabilities)) {
          // If T1, T2 and T3 are all subtypes of double, the static type of e
          // is double.
          return coreTypes.doubleNonNullableRawType;
        }
      }
      // Otherwise the static type of e is num.
      return coreTypes.numNonNullableRawType;
    }
    return coreTypes.numRawType(type1.nullability);
  }

  /// Returns the possibly abstract interface member of [class_] with the given
  /// [name].
  ///
  /// If [setter] is `false`, only fields, methods, and getters with that name
  /// will be found.  If [setter] is `true`, only non-final fields and setters
  /// will be found.
  ///
  /// If multiple members with that name are inherited and not overridden, the
  /// member from the first declared supertype is returned.
  Member? getInterfaceMember(Class cls, Name name, {bool setter: false});
}

/// Tri-state logical result of a nullability-aware subtype check.
class IsSubtypeOf {
  /// Internal value constructed via [IsSubtypeOf.never].
  ///
  /// The integer values of [_valueNever], [_valueOnlyIfIgnoringNullabilities],
  /// and [_valueAlways] are important for the implementations of [_andValues],
  /// [_all], and [and].  They should be kept in sync.
  static const int _valueNever = 0;

  /// Internal value constructed via [IsSubtypeOf.onlyIfIgnoringNullabilities].
  static const int _valueOnlyIfIgnoringNullabilities = 1;

  /// Internal value constructed via [IsSubtypeOf.always].
  static const int _valueAlways = 3;

  static const List<IsSubtypeOf> _all = const <IsSubtypeOf>[
    const IsSubtypeOf.never(),
    const IsSubtypeOf.onlyIfIgnoringNullabilities(),
    // There's no value for this index so we use `IsSubtypeOf.never()` as a
    // dummy value.
    const IsSubtypeOf.never(),
    const IsSubtypeOf.always()
  ];

  /// Combines results of subtype checks on parts into the overall result.
  ///
  /// It's an implementation detail for [and].  See the comment on [and] for
  /// more details and examples.  Both [value1] and [value2] should be chosen
  /// from [_valueNever], [_valueOnlyIfIgnoringNullabilities], and
  /// [_valueAlways].  The method produces the result which is one of
  /// [_valueNever], [_valueOnlyIfIgnoringNullabilities], and [_valueAlways].
  static int _andValues(int value1, int value2) => value1 & value2;

  /// Combines results of the checks on alternatives into the overall result.
  ///
  /// It's an implementation detail for [or].  See the comment on [or] for more
  /// details and examples.  Both [value1] and [value2] should be chosen from
  /// [_valueNever], [_valueOnlyIfIgnoringNullabilities], and [_valueAlways].
  /// The method produces the result which is one of [_valueNever],
  /// [_valueOnlyIfIgnoringNullabilities], and [_valueAlways].
  static int _orValues(int value1, int value2) => value1 | value2;

  /// The only state of an [IsSubtypeOf] object.
  final int _value;

  final DartType? subtype;

  final DartType? supertype;

  const IsSubtypeOf._internal(int value, this.subtype, this.supertype)
      : _value = value;

  /// Subtype check succeeds in both modes.
  const IsSubtypeOf.always() : this._internal(_valueAlways, null, null);

  /// Subtype check succeeds only if the nullability markers are ignored.
  ///
  /// It is assumed that if a subtype check succeeds for two types in full-NNBD
  /// mode, it also succeeds for those two types if the nullability markers on
  /// the types and all of their sub-terms are ignored (that is, in the pre-NNBD
  /// mode).  By contraposition, if a subtype check fails for two types when the
  /// nullability markers are ignored, it should also fail for those types in
  /// full-NNBD mode.
  const IsSubtypeOf.onlyIfIgnoringNullabilities(
      {DartType? subtype, DartType? supertype})
      : this._internal(_valueOnlyIfIgnoringNullabilities, subtype, supertype);

  /// Subtype check fails in both modes.
  const IsSubtypeOf.never() : this._internal(_valueNever, null, null);

  /// Checks if two types are in relation based solely on their nullabilities.
  ///
  /// This is useful on its own if the types are known to be the same modulo the
  /// nullability attribute, but mostly it's useful to combine the result from
  /// [IsSubtypeOf.basedSolelyOnNullabilities] via [and] with the partial
  /// results obtained from other type parts. For example, the overall result
  /// for `List<int>? <: List<num>*` can be computed as `Ra.and(Rn)` where `Ra`
  /// is the result of a subtype check on the arguments `int` and `num`, and
  /// `Rn` is the result of [IsSubtypeOf.basedSolelyOnNullabilities] on the
  /// types `List<int>?` and `List<num>*`.
  factory IsSubtypeOf.basedSolelyOnNullabilities(
      DartType subtype, DartType supertype) {
    if (subtype is InvalidType) {
      if (supertype is InvalidType) {
        return const IsSubtypeOf.always();
      }
      return new IsSubtypeOf.onlyIfIgnoringNullabilities(
          subtype: subtype, supertype: supertype);
    }
    if (supertype is InvalidType) {
      return new IsSubtypeOf.onlyIfIgnoringNullabilities(
          subtype: subtype, supertype: supertype);
    }

    if (subtype.isPotentiallyNullable && supertype.isPotentiallyNonNullable) {
      // It's a special case to test X% <: X%, FutureOr<X%> <: FutureOr<X%>,
      // FutureOr<FutureOr<X%>> <: FutureOr<FutureOr<X%>>, etc, where X is a
      // type parameter.  In that case, the nullabilities of the subtype and the
      // supertype are related, that is, they are both nullable or non-nullable
      // at run time.
      if (subtype.nullability == Nullability.undetermined &&
          supertype.nullability == Nullability.undetermined) {
        DartType unwrappedSubtype = subtype;
        DartType unwrappedSupertype = supertype;
        while (unwrappedSubtype is FutureOrType) {
          unwrappedSubtype = unwrappedSubtype.typeArgument;
        }
        while (unwrappedSupertype is FutureOrType) {
          unwrappedSupertype = unwrappedSupertype.typeArgument;
        }
        if (unwrappedSubtype.nullability == unwrappedSupertype.nullability) {
          // The relationship between the types must be established elsewhere.
          return const IsSubtypeOf.always();
        }
      }
      return new IsSubtypeOf.onlyIfIgnoringNullabilities(
          subtype: subtype, supertype: supertype);
    }
    return const IsSubtypeOf.always();
  }

  /// Combines results for the type parts into the overall result for the type.
  ///
  /// For example, the result of `A<B1, C1> <: A<B2, C2>` can be computed from
  /// the results of the checks `B1 <: B2` and `C1 <: C2`.  Using the binary
  /// outcome of the checks, the combination of the check results on parts is
  /// simply done via `&&`, and [and] is the analog to `&&` for the ternary
  /// outcome.  So, in the example above the overall result is computed as
  /// `Rb.and(Rc)` where `Rb` is the result of `B1 <: B2`, `Rc` is the result
  /// of `C1 <: C2`.
  IsSubtypeOf and(IsSubtypeOf other) {
    int resultValue = _andValues(_value, other._value);
    if (resultValue == IsSubtypeOf._valueOnlyIfIgnoringNullabilities) {
      // If the type mismatch is due to nullabilities, the mismatching parts are
      // remembered in either 'this' or [other].  In that case we need to return
      // exactly one of those objects, so that the information about mismatching
      // parts is propagated upwards.
      if (_value == IsSubtypeOf._valueOnlyIfIgnoringNullabilities) {
        return this;
      } else {
        assert(other._value == IsSubtypeOf._valueOnlyIfIgnoringNullabilities);
        return other;
      }
    } else {
      return _all[resultValue];
    }
  }

  /// Shorts the computation of [and] if `this` is [IsSubtypeOf.never].
  ///
  /// Use this instead of [and] for optimization in case the argument to [and]
  /// is, for example, a potentially expensive subtype check.  Unlike [and],
  /// [andSubtypeCheckFor] will immediately return if `this` was constructed as
  /// [IsSubtypeOf.never] because the right-hand side will not change the
  /// overall result anyway.
  IsSubtypeOf andSubtypeCheckFor(
      DartType subtype, DartType supertype, Types tester) {
    if (_value == _valueNever) return this;
    return this
        .and(tester.performNullabilityAwareSubtypeCheck(subtype, supertype));
  }

  /// Combines results of the checks on alternatives into the overall result.
  ///
  /// For example, the result of `T <: FutureOr<S>` can be computed from the
  /// results of the checks `T <: S` and `T <: Future<S>`.  Using the binary
  /// outcome of the checks, the combination of the check results on parts is
  /// simply done via logical "or", and [or] is the analog to "or" for the
  /// ternary outcome.  So, in the example above the overall result is computed
  /// as `Rs.or(Rf)` where `Rs` is the result of `T <: S`, `Rf` is the result of
  /// `T <: Future<S>`.
  IsSubtypeOf or(IsSubtypeOf other) {
    int resultValue = _orValues(_value, other._value);
    if (resultValue == IsSubtypeOf._valueOnlyIfIgnoringNullabilities) {
      // If the type mismatch is due to nullabilities, the mismatching parts are
      // remembered in either 'this' or [other].  In that case we need to return
      // exactly one of those objects, so that the information about mismatching
      // parts is propagated upwards.
      if (_value == IsSubtypeOf._valueOnlyIfIgnoringNullabilities) {
        return this;
      } else {
        assert(other._value == IsSubtypeOf._valueOnlyIfIgnoringNullabilities);
        return other;
      }
    } else {
      return _all[resultValue];
    }
  }

  /// Shorts the computation of [or] if `this` is [IsSubtypeOf.always].
  ///
  /// Use this instead of [or] for optimization in case the argument to [or] is,
  /// for example, a potentially expensive subtype check.  Unlike [or],
  /// [orSubtypeCheckFor] will immediately return if `this` was constructed
  /// as [IsSubtypeOf.always] because the right-hand side will not change the
  /// overall result anyway.
  IsSubtypeOf orSubtypeCheckFor(
      DartType subtype, DartType supertype, Types tester) {
    if (_value == _valueAlways) return this;
    return this
        .or(tester.performNullabilityAwareSubtypeCheck(subtype, supertype));
  }

  bool isSubtypeWhenIgnoringNullabilities() {
    return _value != _valueNever;
  }

  bool isSubtypeWhenUsingNullabilities() {
    return _value == _valueAlways;
  }

  @override
  String toString() {
    switch (_value) {
      case _valueAlways:
        return "IsSubtypeOf.always";
      case _valueNever:
        return "IsSubtypeOf.never";
      case _valueOnlyIfIgnoringNullabilities:
        return "IsSubtypeOf.onlyIfIgnoringNullabilities";
    }
    return "IsSubtypeOf.<unknown value '${_value}'>";
  }
}

enum SubtypeCheckMode {
  withNullabilities,
  ignoringNullabilities,
}

abstract class StaticTypeCache {
  DartType getExpressionType(Expression node, StaticTypeContext context);

  DartType getForInIteratorType(ForInStatement node, StaticTypeContext context);

  DartType getForInElementType(ForInStatement node, StaticTypeContext context);
}

class StaticTypeCacheImpl implements StaticTypeCache {
  late Map<Expression, DartType> _expressionTypes = {};
  late Map<ForInStatement, DartType> _forInIteratorTypes = {};
  late Map<ForInStatement, DartType> _forInElementTypes = {};

  @override
  DartType getExpressionType(Expression node, StaticTypeContext context) {
    return _expressionTypes[node] ??= node.getStaticTypeInternal(context);
  }

  @override
  DartType getForInIteratorType(
      ForInStatement node, StaticTypeContext context) {
    return _forInIteratorTypes[node] ??= node.getIteratorTypeInternal(context);
  }

  @override
  DartType getForInElementType(ForInStatement node, StaticTypeContext context) {
    return _forInElementTypes[node] ??= node.getElementTypeInternal(context);
  }
}

/// Context object needed for computing `Expression.getStaticType`.
///
/// The [StaticTypeContext] provides access to the [TypeEnvironment] and the
/// current 'this type' as well as determining the nullability state of the
/// enclosing library.
abstract class StaticTypeContext {
  /// The [TypeEnvironment] used for the static type computation.
  ///
  /// This provides access to the core types and the class hierarchy.
  TypeEnvironment get typeEnvironment;

  /// The static type of a `this` expression.
  InterfaceType? get thisType;

  /// Creates a static type context for computing static types in the body
  /// of [member].
  factory StaticTypeContext(Member member, TypeEnvironment typeEnvironment,
      {StaticTypeCache cache}) = StaticTypeContextImpl;

  /// Creates a static type context for computing static types of annotations
  /// in [library].
  factory StaticTypeContext.forAnnotations(
      Library library, TypeEnvironment typeEnvironment,
      {StaticTypeCache cache}) = StaticTypeContextImpl.forAnnotations;

  /// The [Nullability] used for non-nullable types.
  ///
  /// For opt out libraries this is [Nullability.legacy].
  Nullability get nonNullable;

  /// The [Nullability] used for nullable types.
  ///
  /// For opt out libraries this is [Nullability.legacy].
  Nullability get nullable;

  /// Return `true` if the current library is opted in to non-nullable by
  /// default.
  bool get isNonNullableByDefault;

  /// Returns the mode under which the current library was compiled.
  NonNullableByDefaultCompiledMode get nonNullableByDefaultCompiledMode;

  /// Returns the static type of [node].
  DartType getExpressionType(Expression node);

  /// Returns the static type of the iterator in for-in statement [node].
  DartType getForInIteratorType(ForInStatement node);

  /// Returns the static type of the element in for-in statement [node].
  DartType getForInElementType(ForInStatement node);
}

class StaticTypeContextImpl implements StaticTypeContext {
  /// The [TypeEnvironment] used for the static type computation.
  ///
  /// This provides access to the core types and the class hierarchy.
  @override
  final TypeEnvironment typeEnvironment;

  /// The library in which the static type is computed.
  ///
  /// The `library.isNonNullableByDefault` property is used to determine the
  /// nullabilities of the static types.
  final Library _library;

  /// The static type of a `this` expression.
  @override
  final InterfaceType? thisType;

  final StaticTypeCache? _cache;

  /// Creates a static type context for computing static types in the body
  /// of [member].
  StaticTypeContextImpl(Member member, this.typeEnvironment,
      {StaticTypeCache? cache})
      : _library = member.enclosingLibrary,
        thisType = member.enclosingClass?.getThisType(
            typeEnvironment.coreTypes, member.enclosingLibrary.nonNullable),
        _cache = cache;

  /// Creates a static type context for computing static types of annotations
  /// in [library].
  StaticTypeContextImpl.forAnnotations(this._library, this.typeEnvironment,
      {StaticTypeCache? cache})
      : thisType = null,
        _cache = cache;

  /// The [Nullability] used for non-nullable types.
  ///
  /// For opt out libraries this is [Nullability.legacy].
  @override
  Nullability get nonNullable => _library.nonNullable;

  /// The [Nullability] used for nullable types.
  ///
  /// For opt out libraries this is [Nullability.legacy].
  @override
  Nullability get nullable => _library.nullable;

  /// Return `true` if the current library is opted in to non-nullable by
  /// default.
  @override
  bool get isNonNullableByDefault => _library.isNonNullableByDefault;

  /// Returns the mode under which the current library was compiled.
  @override
  NonNullableByDefaultCompiledMode get nonNullableByDefaultCompiledMode =>
      _library.nonNullableByDefaultCompiledMode;

  @override
  DartType getExpressionType(Expression node) {
    if (_cache != null) {
      return _cache!.getExpressionType(node, this);
    } else {
      return node.getStaticTypeInternal(this);
    }
  }

  @override
  DartType getForInIteratorType(ForInStatement node) {
    if (_cache != null) {
      return _cache!.getForInIteratorType(node, this);
    } else {
      return node.getIteratorTypeInternal(this);
    }
  }

  @override
  DartType getForInElementType(ForInStatement node) {
    if (_cache != null) {
      return _cache!.getForInElementType(node, this);
    } else {
      return node.getElementTypeInternal(this);
    }
  }
}

/// Implementation of [StaticTypeContext] that update its state when entering
/// and leaving libraries and members.
abstract class StatefulStaticTypeContext implements StaticTypeContext {
  @override
  final TypeEnvironment typeEnvironment;

  /// Creates a [StatefulStaticTypeContext] that supports entering multiple
  /// libraries and/or members successively.
  factory StatefulStaticTypeContext.stacked(TypeEnvironment typeEnvironment) =
      _StackedStatefulStaticTypeContext;

  /// Creates a [StatefulStaticTypeContext] that only supports entering one
  /// library and/or member at a time.
  factory StatefulStaticTypeContext.flat(TypeEnvironment typeEnvironment) =
      _FlatStatefulStaticTypeContext;

  StatefulStaticTypeContext._internal(this.typeEnvironment);

  /// Updates the [nonNullable] and [thisType] to match static type context for
  /// the member [node].
  ///
  /// This should be called before computing static types on the body of member
  /// [node].
  void enterMember(Member node);

  /// Reverts the [nonNullable] and [thisType] values to the previous state.
  ///
  /// This should be called after computing static types on the body of member
  /// [node].
  void leaveMember(Member node);

  /// Updates the [nonNullable] and [thisType] to match static type context for
  /// the library [node].
  ///
  /// This should be called before computing static types on annotations in the
  /// library [node].
  void enterLibrary(Library node);

  /// Reverts the [nonNullable] and [thisType] values to the previous state.
  ///
  /// This should be called after computing static types on annotations in the
  /// library [node].
  void leaveLibrary(Library node);
}

/// Implementation of [StatefulStaticTypeContext] that only supports entering
/// one library and/or at a time.
class _FlatStatefulStaticTypeContext extends StatefulStaticTypeContext {
  Library? _currentLibrary;
  Member? _currentMember;

  _FlatStatefulStaticTypeContext(TypeEnvironment typeEnvironment)
      : super._internal(typeEnvironment);

  Library get _library {
    Library? library = _currentLibrary ?? _currentMember?.enclosingLibrary;
    assert(library != null,
        "No library currently associated with StaticTypeContext.");
    return library!;
  }

  @override
  InterfaceType? get thisType {
    assert(_currentMember != null,
        "No member currently associated with StaticTypeContext.");
    return _currentMember?.enclosingClass?.getThisType(
        typeEnvironment.coreTypes,
        _currentMember!.enclosingLibrary.nonNullable);
  }

  @override
  Nullability get nonNullable => _library.nonNullable;

  @override
  Nullability get nullable => _library.nullable;

  @override
  bool get isNonNullableByDefault => _library.isNonNullableByDefault;

  @override
  NonNullableByDefaultCompiledMode get nonNullableByDefaultCompiledMode =>
      _library.nonNullableByDefaultCompiledMode;

  /// Updates the [nonNullable] and [thisType] to match static type context for
  /// the member [node].
  ///
  /// This should be called before computing static types on the body of member
  /// [node].
  ///
  /// Only one member can be entered at a time.
  @override
  void enterMember(Member node) {
    assert(_currentMember == null, "Already in context of $_currentMember");
    _currentMember = node;
  }

  /// Reverts the [nonNullable] and [thisType] values to the previous state.
  ///
  /// This should be called after computing static types on the body of member
  /// [node].
  @override
  void leaveMember(Member node) {
    assert(
        _currentMember == node,
        "Inconsistent static type context stack: "
        "Trying to leave $node but current is ${_currentMember}.");
    _currentMember = null;
  }

  /// Updates the [nonNullable] and [thisType] to match static type context for
  /// the library [node].
  ///
  /// This should be called before computing static types on annotations in the
  /// library [node].
  ///
  /// Only one library can be entered at a time, and not while a member is
  /// entered through [enterMember].
  @override
  void enterLibrary(Library node) {
    assert(_currentLibrary == null, "Already in context of $_currentLibrary");
    assert(_currentMember == null, "Already in context of $_currentMember");
    _currentLibrary = node;
  }

  /// Reverts the [nonNullable] and [thisType] values to the previous state.
  ///
  /// This should be called after computing static types on annotations in the
  /// library [node].
  @override
  void leaveLibrary(Library node) {
    assert(
        _currentLibrary == node,
        "Inconsistent static type context stack: "
        "Trying to leave $node but current is ${_currentLibrary}.");
    _currentLibrary = null;
  }

  @override
  DartType getExpressionType(Expression node) =>
      node.getStaticTypeInternal(this);

  @override
  DartType getForInIteratorType(ForInStatement node) =>
      node.getIteratorTypeInternal(this);

  @override
  DartType getForInElementType(ForInStatement node) =>
      node.getElementTypeInternal(this);
}

/// Implementation of [StatefulStaticTypeContext] that use a stack to change
/// state when entering and leaving libraries and members.
class _StackedStatefulStaticTypeContext extends StatefulStaticTypeContext {
  final List<_StaticTypeContextState> _contextStack =
      <_StaticTypeContextState>[];

  _StackedStatefulStaticTypeContext(TypeEnvironment typeEnvironment)
      : super._internal(typeEnvironment);

  Library get _library {
    assert(_contextStack.isNotEmpty,
        "No library currently associated with StaticTypeContext.");
    return _contextStack.last._library;
  }

  @override
  InterfaceType? get thisType {
    assert(_contextStack.isNotEmpty,
        "No this type currently associated with StaticTypeContext.");
    return _contextStack.last._thisType;
  }

  @override
  Nullability get nonNullable => _library.nonNullable;

  @override
  Nullability get nullable => _library.nullable;

  @override
  bool get isNonNullableByDefault => _library.isNonNullableByDefault;

  @override
  NonNullableByDefaultCompiledMode get nonNullableByDefaultCompiledMode =>
      _library.nonNullableByDefaultCompiledMode;

  /// Updates the [library] and [thisType] to match static type context for
  /// the member [node].
  ///
  /// This should be called before computing static types on the body of member
  /// [node].
  @override
  void enterMember(Member node) {
    _contextStack.add(new _StaticTypeContextState(
        node,
        node.enclosingLibrary,
        node.enclosingClass?.getThisType(
            typeEnvironment.coreTypes, node.enclosingLibrary.nonNullable)));
  }

  /// Reverts the [library] and [thisType] values to the previous state.
  ///
  /// This should be called after computing static types on the body of member
  /// [node].
  @override
  void leaveMember(Member node) {
    _StaticTypeContextState state = _contextStack.removeLast();
    assert(
        state._node == node,
        "Inconsistent static type context stack: "
        "Trying to leave $node but current is ${state._node}.");
  }

  /// Updates the [library] and [thisType] to match static type context for
  /// the library [node].
  ///
  /// This should be called before computing static types on annotations in the
  /// library [node].
  @override
  void enterLibrary(Library node) {
    _contextStack.add(new _StaticTypeContextState(node, node, null));
  }

  /// Reverts the [library] and [thisType] values to the previous state.
  ///
  /// This should be called after computing static types on annotations in the
  /// library [node].
  @override
  void leaveLibrary(Library node) {
    _StaticTypeContextState state = _contextStack.removeLast();
    assert(
        state._node == node,
        "Inconsistent static type context stack: "
        "Trying to leave $node but current is ${state._node}.");
  }

  @override
  DartType getExpressionType(Expression node) =>
      node.getStaticTypeInternal(this);

  @override
  DartType getForInIteratorType(ForInStatement node) =>
      node.getIteratorTypeInternal(this);

  @override
  DartType getForInElementType(ForInStatement node) =>
      node.getElementTypeInternal(this);
}

class _StaticTypeContextState {
  final TreeNode _node;
  final Library _library;
  final InterfaceType? _thisType;

  _StaticTypeContextState(this._node, this._library, this._thisType);
}
