// 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.class_hierarchy;

import 'dart:collection';
import 'dart:math';
import 'dart:typed_data';

import 'ast.dart';
import 'core_types.dart';
import 'type_algebra.dart';
import 'src/heap.dart';
import 'src/nnbd_top_merge.dart';
import 'src/norm.dart';

typedef HandleAmbiguousSupertypes = void Function(Class, Supertype, Supertype);

/// Core interface for answering queries needed to compute the subtyping
/// relation.
abstract class ClassHierarchyBase {
  CoreTypes get coreTypes;

  /// Returns the instantiation of [superclass] that is implemented by [class_],
  /// or `null` if [class_] does not implement [superclass] at all.
  Supertype? getClassAsInstanceOf(Class class_, Class superclass);

  /// Returns the instantiation of [typeDeclaration] that is implemented by
  /// [type], or `null` if [type] does not implement [typeDeclaration] at all.
  TypeDeclarationType? getTypeAsInstanceOf(
      TypeDeclarationType type, TypeDeclaration typeDeclaration);

  /// Returns the type arguments of the instantiation of [typeDeclaration] that
  /// is implemented by [type], or `null` if [type] does not implement
  /// [typeDeclaration] at all.
  List<DartType>? getTypeArgumentsAsInstanceOf(
      TypeDeclarationType type, TypeDeclaration typeDeclaration);

  /// Returns the instantiation of [superclass] that is implemented by [type],
  /// or `null` if [type] does not implement [superclass] at all.
  InterfaceType? getInterfaceTypeAsInstanceOfClass(
      InterfaceType type, Class superclass);

  /// Returns the type arguments of the instantiation of [superclass] that is
  /// implemented by [type], or `null` if [type] does not implement [superclass]
  /// at all.
  List<DartType>? getInterfaceTypeArgumentsAsInstanceOfClass(
      InterfaceType type, Class superclass);

  /// Returns the instantiation of [superDeclaration] that is implemented by
  /// [type], or `null` if [type] does not implement [superDeclaration] at all.
  ExtensionType? getExtensionTypeAsInstanceOfExtensionTypeDeclaration(
      ExtensionType type, ExtensionTypeDeclaration superDeclaration);

  /// Returns the instantiation of [superclass] that is implemented by [type],
  /// or `null` if [type] does not implement [superclass] at all.
  InterfaceType? getExtensionTypeAsInstanceOfClass(
      ExtensionType type, Class superclass);

  /// Returns the type arguments of the instantiation of [superDeclaration] that
  /// is implemented by [type], or `null` if [type] does not implement
  /// [superDeclaration] at all.
  List<DartType>? getExtensionTypeArgumentsAsInstanceOfExtensionTypeDeclaration(
      ExtensionType type, ExtensionTypeDeclaration superDeclaration);

  /// Returns the type arguments of the instantiation of [superDeclaration] that
  /// is implemented by [type], or `null` if [type] does not implement
  /// [superDeclaration] at all.
  List<DartType>? getExtensionTypeArgumentsAsInstanceOfClass(
      ExtensionType type, Class superclass);

  /// True if [subtype] inherits from [superclass] though zero or more
  /// `extends`, `with`, and `implements` relationships.
  bool isSubInterfaceOf(Class subtype, Class superclass);

  /// Returns the least upper bound of two interface types, as defined by Dart
  /// 1.0.
  ///
  /// Given two interfaces I and J, let S_I be the set of superinterfaces of I,
  /// let S_J be the set of superinterfaces of J, and let
  /// S = (I union S_I) intersect (J union S_J).  Furthermore, we define
  /// S_n = {T | T in S and depth(T) = n} for any finite n where depth(T) is
  /// the number of steps in the longest inheritance path from T to Object.  Let
  /// q be the largest number such that S_q has cardinality one.  The least
  /// upper bound of I and J is the sole element of S_q.
  ///
  /// This is called the "legacy" least upper bound to distinguish it from the
  /// Dart 2 least upper bound, which has special behaviors in the case where
  /// one type is a subtype of the other, or where both types are based on the
  /// same class.
  InterfaceType getLegacyLeastUpperBound(
      InterfaceType type1, InterfaceType type2);

  /// Computes an upper bound of two types found in their given supertype lists
  ///
  /// This method can be seen as a generalization of [getLegacyLeastUpperBound].
  /// It is expected to work exactly like [getLegacyLeastUpperBound] when
  /// [supertypes1] is `[`[type1]`]` and [supertypes2] is `[`[type2]`]`.
  ///
  /// If either of [type1] or [type2] is an extension type, the corresponding
  /// list of supertypes is its non-extension supertypes of maximal depth. In
  /// that case, the method finds the upper bound for the extension type among
  /// its non-extension supertypes. It is used as a part of the algorithm for
  /// finding the upper bound of extension types.
  InterfaceType getLegacyLeastUpperBoundFromSupertypeLists(
      TypeDeclarationType type1,
      TypeDeclarationType type2,
      List<InterfaceType> supertypes1,
      List<InterfaceType> supertypes2);
}

mixin ClassHierarchyExtensionTypeMixin implements ClassHierarchyBase {
  @override
  TypeDeclarationType? getTypeAsInstanceOf(
      TypeDeclarationType type, TypeDeclaration typeDeclaration) {
    switch (type) {
      case InterfaceType():
        switch (typeDeclaration) {
          case Class():
            return getInterfaceTypeAsInstanceOfClass(type, typeDeclaration);
          case ExtensionTypeDeclaration():
            return null;
        }
      case ExtensionType():
        switch (typeDeclaration) {
          case Class():
            return getExtensionTypeAsInstanceOfClass(type, typeDeclaration);
          case ExtensionTypeDeclaration():
            return getExtensionTypeAsInstanceOfExtensionTypeDeclaration(
                type, typeDeclaration);
        }
    }
  }

  @override
  List<DartType>? getTypeArgumentsAsInstanceOf(
      TypeDeclarationType type, TypeDeclaration typeDeclaration) {
    switch (type) {
      case InterfaceType():
        switch (typeDeclaration) {
          case Class():
            return getInterfaceTypeArgumentsAsInstanceOfClass(
                type, typeDeclaration);
          case ExtensionTypeDeclaration():
            return null;
        }
      case ExtensionType():
        switch (typeDeclaration) {
          case Class():
            return getExtensionTypeArgumentsAsInstanceOfClass(
                type, typeDeclaration);
          case ExtensionTypeDeclaration():
            // ignore: lines_longer_than_80_chars
            return getExtensionTypeArgumentsAsInstanceOfExtensionTypeDeclaration(
                type, typeDeclaration);
        }
    }
  }

  ExtensionType?
      getExtensionTypeDeclarationAsInstanceOfExtensionTypeDeclaration(
          ExtensionTypeDeclaration subDeclaration,
          ExtensionTypeDeclaration superDeclaration) {
    // TODO(johnniwinther): Improve lookup performance.
    if (identical(subDeclaration, superDeclaration)) {
      return coreTypes.thisExtensionType(
          subDeclaration, Nullability.nonNullable);
    }
    for (DartType implement in subDeclaration.implements) {
      if (implement is ExtensionType) {
        ExtensionType? supertype =
            getExtensionTypeDeclarationAsInstanceOfExtensionTypeDeclaration(
                implement.extensionTypeDeclaration, superDeclaration);
        if (supertype != null) {
          if (implement.typeArguments.isNotEmpty) {
            supertype = Substitution.fromExtensionType(implement)
                .substituteType(supertype) as ExtensionType;
          }
          return supertype;
        }
      } else if (implement is InterfaceType) {
        // Extension type declarations cannot be implemented through classes.
      } else {
        assert(
            false,
            "Unexpected supertype $implement extension type declaration of "
            "$subDeclaration.");
      }
    }
    return null;
  }

  InterfaceType? getExtensionTypeDeclarationAsInstanceOfClass(
      ExtensionTypeDeclaration subDeclaration, Class superclass) {
    // TODO(johnniwinther): Improve lookup performance.
    for (DartType implement in subDeclaration.implements) {
      if (implement is ExtensionType) {
        InterfaceType? supertype = getExtensionTypeDeclarationAsInstanceOfClass(
            implement.extensionTypeDeclaration, superclass);
        if (supertype != null) {
          if (implement.typeArguments.isNotEmpty) {
            supertype = Substitution.fromExtensionType(implement)
                .substituteType(supertype) as InterfaceType;
          }
          return supertype;
        }
      } else if (implement is InterfaceType) {
        Supertype? supertype =
            getClassAsInstanceOf(implement.classNode, superclass);
        if (supertype != null) {
          if (implement.typeArguments.isNotEmpty) {
            supertype = Substitution.fromInterfaceType(implement)
                .substituteSupertype(supertype);
          }
          return new InterfaceType(supertype.classNode, Nullability.nonNullable,
              supertype.typeArguments);
        }
      } else {
        assert(
            false,
            "Unexpected supertype $implement extension type declaration of "
            "$subDeclaration.");
      }
    }
    return null;
  }

  @override
  ExtensionType? getExtensionTypeAsInstanceOfExtensionTypeDeclaration(
      ExtensionType type, ExtensionTypeDeclaration superclass) {
    ExtensionType? supertype =
        getExtensionTypeDeclarationAsInstanceOfExtensionTypeDeclaration(
            type.extensionTypeDeclaration, superclass);
    if (supertype != null) {
      if (type.typeArguments.isNotEmpty) {
        supertype = Substitution.fromExtensionType(type)
            .substituteType(supertype) as ExtensionType;
      }
      return supertype;
    }
    return null;
  }

  @override
  InterfaceType? getExtensionTypeAsInstanceOfClass(
      ExtensionType type, Class superclass) {
    InterfaceType? supertype = getExtensionTypeDeclarationAsInstanceOfClass(
        type.extensionTypeDeclaration, superclass);
    if (supertype != null) {
      if (type.typeArguments.isNotEmpty) {
        supertype = Substitution.fromExtensionType(type)
            .substituteType(supertype) as InterfaceType;
      }
      return supertype;
    }
    return null;
  }

  @override
  List<DartType>? getExtensionTypeArgumentsAsInstanceOfExtensionTypeDeclaration(
      ExtensionType type, ExtensionTypeDeclaration superDeclaration) {
    return getExtensionTypeAsInstanceOfExtensionTypeDeclaration(
            type, superDeclaration)
        ?.typeArguments;
  }

  @override
  List<DartType>? getExtensionTypeArgumentsAsInstanceOfClass(
      ExtensionType type, Class superclass) {
    return getExtensionTypeAsInstanceOfClass(type, superclass)?.typeArguments;
  }
}

abstract class ClassHierarchyMembers {
  /// Returns the instance member that would respond to a dynamic dispatch of
  /// [name] to an instance of [class_], or `null` if no such member exists.
  ///
  /// If [setter] is `false`, the name is dispatched as a getter or call,
  /// and will return a field, getter, method, or operator (or null).
  ///
  /// If [setter] is `true`, the name is dispatched as a setter, roughly
  /// corresponding to `name=` in the Dart specification, but note that the
  /// returned member will not have a name ending with `=`.  In this case,
  /// a non-final field or setter (or null) will be returned.
  ///
  /// If the class is abstract, abstract members are ignored and the dispatch
  /// is resolved if the class was not abstract.
  Member? getDispatchTarget(Class class_, Name name, {bool setter = false});

  /// 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 class_, Name name, {bool setter = false});
}

/// Interface for answering various subclassing queries.
abstract class ClassHierarchy
    implements ClassHierarchyBase, ClassHierarchyMembers {
  factory ClassHierarchy(Component component, CoreTypes coreTypes,
      {HandleAmbiguousSupertypes? onAmbiguousSupertypes}) {
    onAmbiguousSupertypes ??= (Class cls, Supertype a, Supertype b) {
      // See https://github.com/dart-lang/sdk/issues/32091
      throw "$cls can't implement both $a and $b";
    };
    return new ClosedWorldClassHierarchy._internal(
        coreTypes, onAmbiguousSupertypes)
      .._initialize(component.libraries);
  }

  void set coreTypes(CoreTypes coreTypes);

  /// Given the [unordered] classes, return them in such order that classes
  /// occur after their superclasses.  If some superclasses are not in
  /// [unordered], they are not included.
  Iterable<Class> getOrderedClasses(Iterable<Class> unordered);

  /// Returns the list of potential targets of dynamic dispatch to an instance
  /// of [class_].
  ///
  /// If [setters] is `false`, only potential targets of a getter or call
  /// dispatch are returned.  If [setters] is `true`, only potential targets
  /// of a setter dispatch are returned.
  ///
  /// See [getDispatchTarget] for more details.
  ///
  /// The returned list should not be modified.
  List<Member> getDispatchTargets(Class class_, {bool setters = false});

  /// Returns the list of members denoting the interface for [class_], which
  /// may include abstract members.
  ///
  /// The list may contain multiple members with a given name.  This happens
  /// when members are inherited through different supertypes and not overridden
  /// in the class.
  ///
  /// Also see [getInterfaceMember].
  List<Member> getInterfaceMembers(Class class_, {bool setters = false});

  /// Returns the list of members declared in [class_], including abstract
  /// members.
  ///
  /// Members are sorted by name so that they may be efficiently compared across
  /// classes.
  List<Member> getDeclaredMembers(Class class_, {bool setters = false});

  /// True if [subclass] inherits from [superclass] though zero or more
  /// `extends` relationships.
  bool isSubclassOf(Class subclass, Class superclass);

  /// Returns the set of libraries for which this class hierarchy can be
  /// queried.
  ///
  /// Classes outside the set of known libraries are not part of the internal
  /// model and queries about such classes will fail.
  Iterable<Library> get knownLibraries;

  /// Invokes [callback] for every member declared in or inherited by [class_]
  /// that overrides or implements a member in a supertype of [class_]
  /// (or in rare cases, overrides a member declared in [class_]).
  ///
  /// We use the term "inheritable" for members that are candidates for
  /// inheritance but may have been overridden.  The "declared" members of a
  /// mixin application are those declared in the mixed-in type. The callback is
  /// invoked in the following cases:
  ///
  /// 1. A member declared in the class overrides a member inheritable through
  /// one of the supertypes of the class.
  ///
  /// 2. A non-abstract member is inherited from a superclass, and in the
  /// context of this class, it overrides an abstract member inheritable through
  /// one of its superinterfaces.
  ///
  /// 3. A non-abstract member is inherited from a superclass, and it overrides
  /// an abstract member declared in this class.
  ///
  /// This method will not report that a member overrides itself. A given pair
  /// may be reported multiple times when there are multiple inheritance paths
  /// to the overridden member.
  ///
  /// It is possible for two methods to override one another in both directions.
  ///
  /// By default getters and setters are overridden separately.  The [isSetter]
  /// callback parameter determines which type of access is being overridden.
  void forEachOverridePair(Class class_,
      callback(Member declaredMember, Member interfaceMember, bool isSetter));

  /// This method is invoked by the client after a change: removal, addition,
  /// or modification of classes (via libraries).
  ///
  /// For modified classes specify a class as both removed and added: Some of
  /// the information that this hierarchy might have cached, is not valid
  /// anymore.
  ///
  /// Note, that it is the clients responsibility to mark all subclasses as
  /// changed too.
  // TODO(johnniwinther): Support class hierarchy changes directly. Currently
  // we can handle added superclasses but not removed superclasses.
  ClassHierarchy applyTreeChanges(Iterable<Library> removedLibraries,
      Iterable<Library> ensureKnownLibraries, Iterable<Class> updatedClasses,
      {Component reissueAmbiguousSupertypesFor});

  /// This method is invoked by the client after a member change on classes:
  /// Some of the information that this hierarchy might have cached,
  /// is not valid anymore.
  /// Note, that it is the clients responsibility to mark all subclasses as
  /// changed too, or - if [findDescendants] is true, the ClassHierarchy will
  /// spend the time to find them for the caller.
  ClassHierarchy applyMemberChanges(Iterable<Class> classes,
      {bool findDescendants = false});

  /// Merges two sorted lists.
  ///
  /// If a given member occurs in both lists, the merge will attempt to exclude
  /// the duplicate member, but is not strictly guaranteed to do so.
  ///
  /// The sort has the following stability properties:
  ///
  /// - If both x and y came from the same input list, and x preceded y in the
  ///   input list, x will precede y in the output list.  This holds even if x
  ///   and y have matching names.
  ///
  /// - If m is a contiguous subsequence of the output list containing at least
  ///   one element from each input list, and all elements of m have matching
  ///   names, then the elements of m from [first] will precede the elements of
  ///   m from [second].
  static List<Member> mergeSortedLists(
      List<Member> first, List<Member> second) {
    if (first.isEmpty) return second;
    if (second.isEmpty) return first;
    List<Member> result = new List<Member>.filled(
        first.length + second.length, dummyMember,
        growable: true);
    int storeIndex = 0;
    int i = 0, j = 0;
    while (i < first.length && j < second.length) {
      Member firstMember = first[i];
      Member secondMember = second[j];
      int compare = ClassHierarchy.compareMembers(firstMember, secondMember);
      if (compare <= 0) {
        result[storeIndex++] = firstMember;
        ++i;
        // If the same member occurs in both lists, skip the duplicate.
        if (identical(firstMember, secondMember)) {
          ++j;
        }
      } else {
        result[storeIndex++] = secondMember;
        ++j;
      }
    }
    while (i < first.length) {
      result[storeIndex++] = first[i++];
    }
    while (j < second.length) {
      result[storeIndex++] = second[j++];
    }
    result.length = storeIndex;
    return result;
  }

  /// Compares members by name, using the same sort order as
  /// [getDeclaredMembers] and [getInterfaceMembers].
  static int compareMembers(Member first, Member second) {
    if (first == second) return 0;
    return compareNames(first.name, second.name);
  }

  /// Compares names, using the same sort order as [getDeclaredMembers] and
  /// [getInterfaceMembers].
  ///
  /// This is an arbitrary as-fast-as-possible sorting criterion.
  static int compareNames(Name firstName, Name secondName) {
    int firstHash = firstName.hashCode;
    int secondHash = secondName.hashCode;
    if (firstHash != secondHash) return firstHash - secondHash;
    String firstString = firstName.text;
    String secondString = secondName.text;
    int firstLength = firstString.length;
    int secondLength = secondString.length;
    if (firstLength != secondLength) {
      return firstLength - secondLength;
    }
    Library? firstLibrary = firstName.library;
    Library? secondLibrary = secondName.library;
    if (firstLibrary != secondLibrary) {
      if (firstLibrary == null) return -1;
      if (secondLibrary == null) return 1;
      return firstLibrary.compareTo(secondLibrary);
    }
    for (int i = 0; i < firstLength; ++i) {
      int firstUnit = firstString.codeUnitAt(i);
      int secondUnit = secondString.codeUnitAt(i);
      int delta = firstUnit - secondUnit;
      if (delta != 0) return delta;
    }
    return 0;
  }

  /// Returns the member with the given name, or `null` if no member has the
  /// name.  In case the list contains multiple members with the given name,
  /// the one that occurs first in the list is returned.
  ///
  /// The list is assumed to be sorted according to [compareMembers].
  static Member? findMemberByName(List<Member> members, Name name) {
    int low = 0, high = members.length - 1;
    while (low <= high) {
      int mid = low + ((high - low) >> 1);
      Member pivot = members[mid];
      int comparison = compareNames(name, pivot.name);
      if (comparison < 0) {
        high = mid - 1;
      } else if (comparison > 0) {
        low = mid + 1;
      } else if (high != mid) {
        // Ensure we find the first element of the given name.
        high = mid;
      } else {
        return pivot;
      }
    }
    return null;
  }
}

abstract class ClassHierarchySubtypes {
  /// Returns the subtypes of [class_] as an interval list.
  ClassSet getSubtypesOf(Class class_);

  /// Returns the single concrete target for invocation of the given interface
  /// target, or `null` if it could not be resolved or there are multiple
  /// possible targets.
  Member? getSingleTargetForInterfaceInvocation(Member interfaceTarget,
      {bool setter = false});
}

class _ClassInfoSubtype {
  final _ClassInfo classInfo;
  int topDownIndex = -1;

  /// Top-down indices of all subclasses of this class, represented as
  /// interleaved begin/end interval end points.
  late final Uint32List subtypeIntervalList;

  _ClassInfoSubtype(this.classInfo);
}

class _ClosedWorldClassHierarchySubtypes implements ClassHierarchySubtypes {
  final ClosedWorldClassHierarchy hierarchy;
  final List<Class?> _classesByTopDownIndex;
  final Map<Class, _ClassInfoSubtype> _infoMap = <Class, _ClassInfoSubtype>{};
  bool invalidated = false;

  _ClosedWorldClassHierarchySubtypes(this.hierarchy)
      : _classesByTopDownIndex =
            new List<Class?>.filled(hierarchy._infoMap.length, null) {
    hierarchy.allBetsOff = true;
    if (hierarchy._infoMap.isNotEmpty) {
      for (Class class_ in hierarchy._infoMap.keys) {
        _infoMap[class_] = new _ClassInfoSubtype(hierarchy._infoMap[class_]!);
      }

      _topDownSortVisit(_infoMap[hierarchy._infoMap.keys.first]!);
    }
  }

  /// Downwards traversal of the class hierarchy that orders classes so local
  /// hierarchies have contiguous indices.
  int _topDownSortIndex = 0;
  void _topDownSortVisit(_ClassInfoSubtype subInfo) {
    if (subInfo.topDownIndex != -1) return;
    int index = _topDownSortIndex++;
    subInfo.topDownIndex = index;
    _classesByTopDownIndex[index] = subInfo.classInfo.classNode;
    _IntervalListBuilder subtypeSetBuilder = new _IntervalListBuilder()
      ..addSingleton(index);
    for (_ClassInfo subtype in subInfo.classInfo.directExtenders) {
      _ClassInfoSubtype subtypeInfo = _infoMap[subtype.classNode]!;
      _topDownSortVisit(subtypeInfo);
      subtypeSetBuilder.addIntervalList(subtypeInfo.subtypeIntervalList);
    }
    for (_ClassInfo subtype in subInfo.classInfo.directMixers) {
      _ClassInfoSubtype subtypeInfo = _infoMap[subtype.classNode]!;
      _topDownSortVisit(subtypeInfo);
      subtypeSetBuilder.addIntervalList(subtypeInfo.subtypeIntervalList);
    }
    for (_ClassInfo subtype in subInfo.classInfo.directImplementers) {
      _ClassInfoSubtype subtypeInfo = _infoMap[subtype.classNode]!;
      _topDownSortVisit(subtypeInfo);
      subtypeSetBuilder.addIntervalList(subtypeInfo.subtypeIntervalList);
    }
    subInfo.subtypeIntervalList = subtypeSetBuilder.buildIntervalList();
  }

  @override
  Member? getSingleTargetForInterfaceInvocation(Member interfaceTarget,
      {bool setter = false}) {
    if (invalidated) throw "This data structure has been invalidated";
    Name name = interfaceTarget.name;
    Member? target = null;
    ClassSet subtypes = getSubtypesOf(interfaceTarget.enclosingClass!);
    for (Class c in subtypes) {
      if (!c.isAbstract) {
        Member? candidate =
            hierarchy.getDispatchTarget(c, name, setter: setter);
        if ((candidate != null) && !candidate.isAbstract) {
          if (target == null) {
            target = candidate;
          } else if (target != candidate) {
            return null;
          }
        }
      }
    }
    return target;
  }

  @override
  ClassSet getSubtypesOf(Class class_) {
    if (invalidated) throw "This data structure has been invalidated";
    Set<Class> result = new Set<Class>();
    Uint32List list = _infoMap[class_]!.subtypeIntervalList;
    for (int i = 0; i < list.length; i += 2) {
      int from = list[i];
      int to = list[i + 1];
      for (int j = from; j < to; j++) {
        result.add(_classesByTopDownIndex[j]!);
      }
    }
    return new ClassSet(result);
  }
}

/// Implementation of [ClassHierarchy] for closed world.
class ClosedWorldClassHierarchy
    with ClassHierarchyExtensionTypeMixin
    implements ClassHierarchy {
  @override
  CoreTypes coreTypes;
  late HandleAmbiguousSupertypes _onAmbiguousSupertypes;
  late HandleAmbiguousSupertypes _onAmbiguousSupertypesNotWrapped;

  /// The insert order is important.
  final Map<Class, _ClassInfo> _infoMap =
      new LinkedHashMap<Class, _ClassInfo>();

  List<ForTestingClassInfo> getTestingClassInfo() {
    List<ForTestingClassInfo> result = <ForTestingClassInfo>[];
    for (_ClassInfo info in _infoMap.values) {
      result.add(new ForTestingClassInfo._(info));
    }
    return result;
  }

  List<Class> getAllSupertypeClassesForTesting(Class class_) {
    List<Class?> allClassesByIndex =
        new List<Class?>.filled(_infoMap.length, null);
    for (MapEntry<Class, _ClassInfo> c in _infoMap.entries) {
      allClassesByIndex[c.value.topologicalIndex] = c.key;
    }

    List<Class> result = [];
    Uint32List list = _infoMap[class_]!.supertypeIntervalList;
    for (int i = 0; i < list.length; i += 2) {
      int from = list[i];
      int to = list[i + 1];
      for (int j = from; j < to; j++) {
        result.add(allClassesByIndex[j]!);
      }
    }
    return result;
  }

  _ClassInfo infoFor(Class cls) {
    _ClassInfo? info = _infoMap[cls];
    if (info == null) {
      throw "${cls.fileUri}: No class info for ${cls.name}";
    }
    info.used = true;
    return info;
  }

  List<Class> getUsedClasses() {
    List<Class> result = <Class>[];
    for (_ClassInfo classInfo in _infoMap.values) {
      if (classInfo.used) {
        result.add(classInfo.classNode);
      }
    }
    return result;
  }

  void resetUsed() {
    for (_ClassInfo classInfo in _infoMap.values) {
      classInfo.used = false;
    }
    allBetsOff = false;
  }

  @override
  final Set<Library> knownLibraries = new Set<Library>();
  bool allBetsOff = false;

  /// Recorded errors for classes we have already calculated the class hierarchy
  /// for, but will have to be reissued when re-using the calculation.
  final Map<Class, List<Supertype>> _recordedAmbiguousSupertypes =
      new LinkedHashMap<Class, List<Supertype>>();

  Iterable<Class> get classes {
    allBetsOff = true;
    return _infoMap.keys;
  }

  _ClosedWorldClassHierarchySubtypes? _cachedClassHierarchySubtypes;

  ClosedWorldClassHierarchy._internal(
      this.coreTypes, HandleAmbiguousSupertypes onAmbiguousSupertypes) {
    _onAmbiguousSupertypesNotWrapped = onAmbiguousSupertypes;
    _onAmbiguousSupertypes = (Class class_, Supertype a, Supertype b) {
      onAmbiguousSupertypes(class_, a, b);
      List<Supertype>? recorded = _recordedAmbiguousSupertypes[class_];
      if (recorded == null) {
        recorded = <Supertype>[];
        _recordedAmbiguousSupertypes[class_] = recorded;
      }
      recorded.add(a);
      recorded.add(b);
    };
  }

  ClassHierarchySubtypes computeSubtypesInformation() {
    _cachedClassHierarchySubtypes ??=
        new _ClosedWorldClassHierarchySubtypes(this);
    return _cachedClassHierarchySubtypes!;
  }

  @override
  Iterable<Class> getOrderedClasses(Iterable<Class> unordered) {
    Set<Class> unorderedSet = unordered.toSet();
    for (Class c in unordered) {
      _infoMap[c]?.used = true;
    }
    return _infoMap.keys.where(unorderedSet.contains);
  }

  @override
  bool isSubclassOf(Class subclass, Class superclass) {
    if (identical(subclass, superclass)) return true;
    return infoFor(subclass).isSubclassOf(infoFor(superclass));
  }

  @override
  bool isSubInterfaceOf(Class subtype, Class superclass) {
    if (identical(subtype, superclass)) return true;
    return infoFor(subtype).isSubtypeOf(infoFor(superclass));
  }

  List<_ClassInfo> _getRankedSuperclassInfos(_ClassInfo info) {
    if (info.leastUpperBoundInfos != null) return info.leastUpperBoundInfos!;
    _LubHeap heap = new _LubHeap()..add(info);
    List<_ClassInfo> chain = <_ClassInfo>[];
    info.leastUpperBoundInfos = chain;
    _ClassInfo? lastInfo = null;
    while (heap.isNotEmpty) {
      _ClassInfo nextInfo = heap.remove();
      if (identical(nextInfo, lastInfo)) continue;
      chain.add(nextInfo);
      lastInfo = nextInfo;
      Class classNode = nextInfo.classNode;
      void addToHeap(Supertype supertype) {
        heap.add(infoFor(supertype.classNode));
      }

      Supertype? supertype = classNode.supertype;
      if (supertype != null) {
        addToHeap(supertype);
      }
      Supertype? mixedInType = classNode.mixedInType;
      if (mixedInType != null) {
        addToHeap(mixedInType);
      }
      classNode.implementedTypes.forEach(addToHeap);
    }
    return chain;
  }

  List<_ClassInfo> _getCombinedRankedSuperclassInfosFromList(
      List<_ClassInfo> infos) {
    if (infos.length == 1 && infos.single.leastUpperBoundInfos != null) {
      return infos.single.leastUpperBoundInfos!;
    }

    _LubHeap heap = new _LubHeap();
    for (_ClassInfo info in infos) {
      heap.add(info);
      if (info.leastUpperBoundInfos == null) {
        List<_ClassInfo> chainForInfo = _getRankedSuperclassInfos(info);
        for (_ClassInfo fromChain in chainForInfo) {
          heap.add(fromChain);
        }
      }
    }

    List<_ClassInfo> chain = <_ClassInfo>[];
    while (heap.isNotEmpty) {
      _ClassInfo info = heap.remove();
      chain.add(info);
    }

    return chain;
  }

  @override
  InterfaceType getLegacyLeastUpperBound(
      InterfaceType type1, InterfaceType type2) {
    // The algorithm is: first we compute a list of superclasses for both types,
    // ordered from greatest to least depth, and ordered by topological sort
    // index within each depth.  Due to the sort order, we can find the
    // intersection of these lists by a simple walk.
    //
    // Then, for each class in the intersection, determine the exact type that
    // is implemented by type1 and type2.  If the types match, that type is a
    // candidate (it's a member of S_n).  As soon as we find a candidate which
    // is unique for its depth, we return it.
    //
    // As an optimization, if the class for I is a subtype of the class for J,
    // then we know that the list of superclasses of J is a subset of the list
    // of superclasses for I; therefore it is sufficient to compute just the
    // list of superclasses for J.  To avoid complicating the code below (which
    // intersects the two lists), we set both lists equal to the list of
    // superclasses for J.  And vice versa with the role of I and J swapped.

    // Compute the list of superclasses for both types, with the above
    // optimization.

    _ClassInfo info1 = infoFor(type1.classNode);
    _ClassInfo info2 = infoFor(type2.classNode);
    List<_ClassInfo> classes1;
    List<_ClassInfo> classes2;
    if (identical(info1, info2) || info1.isSubtypeOf(info2)) {
      classes1 = classes2 = _getRankedSuperclassInfos(info2);
    } else if (info2.isSubtypeOf(info1)) {
      classes1 = classes2 = _getRankedSuperclassInfos(info1);
    } else {
      classes1 = _getRankedSuperclassInfos(info1);
      classes2 = _getRankedSuperclassInfos(info2);
    }

    return _getLegacyLeastUpperBoundInternal(
        type1, type2, info1, info2, classes1, classes2);
  }

  InterfaceType _getLegacyLeastUpperBoundInternal(
      TypeDeclarationType type1,
      TypeDeclarationType type2,
      _ClassInfo? info1,
      _ClassInfo? info2,
      List<_ClassInfo> classInfos1,
      List<_ClassInfo> classInfos2) {
    assert(type1 is! InterfaceType || info1 != null);
    assert(type2 is! InterfaceType || info2 != null);

    // Walk the lists finding their intersection, looking for a depth that has a
    // single candidate.
    int i1 = 0;
    int i2 = 0;
    InterfaceType? candidate = null;
    int currentDepth = -1;
    int numCandidatesAtThisDepth = 0;
    while (true) {
      _ClassInfo next = classInfos1[i1];
      _ClassInfo next2 = classInfos2[i2];
      if (!identical(next, next2)) {
        if (_LubHeap.sortsBeforeStatic(next, next2)) {
          ++i1;
        } else {
          ++i2;
        }
        continue;
      }
      ++i2;
      ++i1;
      if (next.classNode.isAnonymousMixin) {
        // Never find unnamed mixin application in least upper bound.
        continue;
      }
      if (next.depth != currentDepth) {
        if (numCandidatesAtThisDepth == 1) {
          return candidate!;
        }
        currentDepth = next.depth;
        numCandidatesAtThisDepth = 0;
        candidate = null;
      } else if (numCandidatesAtThisDepth > 1) {
        continue;
      }

      // For each class in the intersection, find the exact type that is
      // implemented by type1 and type2.  If they match, it's a candidate.
      //
      // Two additional optimizations:
      //
      // - If this class lacks type parameters, we know there is a match without
      //   needing to substitute.
      //
      // - If the depth is 0, we have reached Object, so we can return it
      //   immediately.  Since all interface types are subtypes of Object, this
      //   ensures the loop terminates.
      if (next.classNode.typeParameters.isEmpty) {
        candidate = coreTypes.rawType(next.classNode,
            uniteNullabilities(type1.nullability, type2.nullability));
        if (currentDepth == 0) return candidate;
        ++numCandidatesAtThisDepth;
      } else {
        InterfaceType superType1;
        if (type1 is InterfaceType) {
          superType1 = identical(info1!, next)
              ? type1
              : Substitution.fromInterfaceType(type1).substituteType(
                      info1.genericSuperType![next.classNode]!.asInterfaceType)
                  as InterfaceType;
        } else {
          type1 as ExtensionType;
          superType1 =
              getExtensionTypeAsInstanceOfClass(type1, next.classNode)!;
        }

        InterfaceType superType2;
        if (type2 is InterfaceType) {
          superType2 = identical(info2!, next)
              ? type2
              : Substitution.fromInterfaceType(type2).substituteType(
                      info2.genericSuperType![next.classNode]!.asInterfaceType)
                  as InterfaceType;
        } else {
          type2 as ExtensionType;
          superType2 =
              getExtensionTypeAsInstanceOfClass(type2, next.classNode)!;
        }

        if (superType1 == superType2) {
          candidate = superType1.withDeclaredNullability(
              uniteNullabilities(type1.nullability, type2.nullability));
          ++numCandidatesAtThisDepth;
        }
      }
    }
  }

  @override
  InterfaceType getLegacyLeastUpperBoundFromSupertypeLists(
      TypeDeclarationType type1,
      TypeDeclarationType type2,
      List<InterfaceType> supertypes1,
      List<InterfaceType> supertypes2) {
    assert(supertypes1.isNotEmpty || type1 is ExtensionType);
    assert(supertypes2.isNotEmpty || type2 is ExtensionType);

    if (supertypes1.isEmpty || supertypes2.isEmpty) {
      if (type1 is ExtensionType && type1.isPotentiallyNullable ||
          type2 is ExtensionType && type2.isPotentiallyNullable) {
        return coreTypes.objectNullableRawType;
      } else {
        return coreTypes.objectRawType(
            uniteNullabilities(type1.nullability, type2.nullability));
      }
    }

    List<_ClassInfo> combinedInfos1 =
        _getCombinedRankedSuperclassInfosFromList(<_ClassInfo>[
      for (InterfaceType supertype in supertypes1) infoFor(supertype.classNode)
    ]);
    List<_ClassInfo> combinedInfos2 =
        _getCombinedRankedSuperclassInfosFromList(<_ClassInfo>[
      for (InterfaceType supertype in supertypes2) infoFor(supertype.classNode)
    ]);

    return _getLegacyLeastUpperBoundInternal(
        type1,
        type2,
        type1 is InterfaceType ? infoFor(type1.classNode) : null,
        type2 is InterfaceType ? infoFor(type2.classNode) : null,
        combinedInfos1,
        combinedInfos2);
  }

  @override
  Supertype? getClassAsInstanceOf(Class class_, Class superclass) {
    if (identical(class_, superclass)) return class_.asThisSupertype;
    _ClassInfo info = infoFor(class_);
    _ClassInfo superInfo = infoFor(superclass);
    if (!info.isSubtypeOf(superInfo)) return null;
    if (superclass.typeParameters.isEmpty) return superclass.asRawSupertype;
    assert(info.genericSuperType!.containsKey(superclass),
        "No canonical instance of $superclass found for $class_.");
    return info.genericSuperType![superclass];
  }

  @override
  InterfaceType? getInterfaceTypeAsInstanceOfClass(
      InterfaceType type, Class superclass) {
    List<DartType>? typeArguments =
        getInterfaceTypeArgumentsAsInstanceOfClass(type, superclass);
    if (typeArguments == null) return null;
    return new InterfaceType(superclass, type.nullability, typeArguments);
  }

  @override
  List<DartType>? getInterfaceTypeArgumentsAsInstanceOfClass(
      InterfaceType type, Class superclass) {
    if (type.classReference == superclass.reference) {
      // TODO(johnniwinther): This is necessary because [getClassAsInstanceOf]
      // returns a [Supertype] whose type arguments are type parameter types
      // whose nullability is set to the default nullability of the
      // enclosing library. If for instance [type] is `A<int!>` but `A` is
      // declared in an opt-out library, the substitution below will combine
      // nullabilities of the type arguments in [type] with the type parameters
      // and thus give the result `A<int*>`. See issue #42792.
      // For now we bypass the substitution but long term we need to ensure
      // that [getClassAsInstanceOf] doesn't cause similar problems in other
      // situations.
      return type.typeArguments;
    }
    Supertype? castedType = getClassAsInstanceOf(type.classNode, superclass);
    if (castedType == null) return null;
    if (superclass.typeParameters.isEmpty) return const <DartType>[];
    return Substitution.fromInterfaceType(type)
        .substituteSupertype(castedType)
        .typeArguments;
  }

  @override
  Member? getDispatchTarget(Class class_, Name name, {bool setter = false}) {
    List<Member> list =
        _buildImplementedMembers(class_, infoFor(class_), setters: setter);
    Member? member = ClassHierarchy.findMemberByName(list, name);
    assert(
        member == null || !member.isAbstract,
        "Abstract member $member found as dispatch target "
        "for $name on $class_");
    return member;
  }

  @override
  List<Member> getDispatchTargets(Class class_, {bool setters = false}) {
    return _buildImplementedMembers(class_, infoFor(class_), setters: setters);
  }

  @override
  Member? getInterfaceMember(Class class_, Name name, {bool setter = false}) {
    List<Member> list = getInterfaceMembers(class_, setters: setter);
    return ClassHierarchy.findMemberByName(list, name);
  }

  @override
  List<Member> getInterfaceMembers(Class class_, {bool setters = false}) {
    return _buildInterfaceMembers(class_, infoFor(class_), setters: setters);
  }

  @override
  List<Member> getDeclaredMembers(Class class_, {bool setters = false}) {
    return _buildDeclaredMembers(class_, infoFor(class_), setters: setters);
  }

  @override
  void forEachOverridePair(Class class_,
      callback(Member declaredMember, Member interfaceMember, bool isSetter),
      {bool crossGettersSetters = false}) {
    _ClassInfo info = infoFor(class_);
    for (Supertype supertype in class_.supers) {
      Class superclass = supertype.classNode;
      List<Member> superGetters = getInterfaceMembers(superclass);
      List<Member> superSetters =
          getInterfaceMembers(superclass, setters: true);
      _reportOverrides(_buildDeclaredMembers(class_, info, setters: false),
          superGetters, callback);
      _reportOverrides(_buildDeclaredMembers(class_, info, setters: true),
          superSetters, callback,
          isSetter: true);
    }
  }

  static void _reportOverrides(
      List<Member> declaredList,
      List<Member> inheritedList,
      callback(Member declaredMember, Member interfaceMember, bool isSetter),
      {bool isSetter = false}) {
    int i = 0, j = 0;
    while (i < declaredList.length && j < inheritedList.length) {
      Member declared = declaredList[i];
      Member inherited = inheritedList[j];
      int comparison = ClassHierarchy.compareMembers(declared, inherited);
      if (comparison < 0) {
        ++i;
      } else if (comparison > 0) {
        ++j;
      } else {
        if (!identical(declared, inherited)) {
          callback(declared, inherited, isSetter);
        }
        // A given declared member may override multiple interface members,
        // so only move past the interface member.
        ++j;
      }
    }
  }

  // Returns the instantiation of each generic supertype implemented by this
  // class (e.g. getClassAsInstanceOf applied to all superclasses and
  // interfaces).
  List<Supertype> genericSupertypesOf(Class class_) {
    Map<Class, Supertype>? supertypes = infoFor(class_).genericSuperType;
    if (supertypes == null) return const <Supertype>[];
    return supertypes.values.toList();
  }

  @override
  ClassHierarchy applyTreeChanges(Iterable<Library> removedLibraries,
      Iterable<Library> ensureKnownLibraries, Iterable<Class> updatedClasses,
      {Component? reissueAmbiguousSupertypesFor}) {
    Set<_ClassInfo> changedClasses = <_ClassInfo>{};

    void removeClass(Class cls) {
      _ClassInfo? info = _infoMap[cls];
      if (info == null) return;
      Supertype? supertype = cls.supertype;
      if (supertype != null) {
        _infoMap[supertype.classNode]?.directExtenders.remove(info);
      }
      Supertype? mixedInType = cls.mixedInType;
      if (mixedInType != null) {
        _infoMap[mixedInType.classNode]?.directMixers.remove(info);
      }
      for (Supertype supertype in cls.implementedTypes) {
        _infoMap[supertype.classNode]?.directImplementers.remove(info);
        // Remove from directMixers too as the mixin transformation will
        // "move" the type here.
        if (cls.isAnonymousMixin || cls.isEliminatedMixin) {
          _infoMap[supertype.classNode]?.directMixers.remove(info);
        }
      }
      _infoMap.remove(cls);
      _recordedAmbiguousSupertypes.remove(cls);
    }

    void invalidateClass(_ClassInfo? info) {
      if (info == null) return;
      if (!changedClasses.add(info)) return;
      for (_ClassInfo i in info.directExtenders.toList()) {
        invalidateClass(i);
      }
      for (_ClassInfo i in info.directMixers.toList()) {
        invalidateClass(i);
      }
      for (_ClassInfo i in info.directImplementers.toList()) {
        invalidateClass(i);
      }
      removeClass(info.classNode);
    }

    for (Class cls in updatedClasses) {
      invalidateClass(_infoMap[cls]);
    }

    // Remove all references to the removed classes.
    for (Library lib in removedLibraries) {
      if (!knownLibraries.contains(lib)) continue;
      for (Class class_ in lib.classes) {
        removeClass(class_);
      }
      knownLibraries.remove(lib);
    }

    // If we have a cached computation of subtypes, invalidate it and stop
    // caching it.
    if (_cachedClassHierarchySubtypes != null) {
      _cachedClassHierarchySubtypes!.invalidated = true;
    }

    if (_recordedAmbiguousSupertypes.isNotEmpty &&
        reissueAmbiguousSupertypesFor != null) {
      Set<Library> libs =
          new Set<Library>.of(reissueAmbiguousSupertypesFor.libraries);
      for (Class class_ in _recordedAmbiguousSupertypes.keys) {
        if (!libs.contains(class_.enclosingLibrary)) continue;
        List<Supertype> recorded = _recordedAmbiguousSupertypes[class_]!;
        for (int i = 0; i < recorded.length; i += 2) {
          _onAmbiguousSupertypesNotWrapped(
              class_, recorded[i], recorded[i + 1]);
        }
      }
    }

    // Add the new classes.
    List<Class> addedClassesSorted = <Class>[];
    int expectedStartIndex = _topSortIndex;
    for (Library lib in ensureKnownLibraries) {
      if (knownLibraries.contains(lib)) continue;
      for (Class class_ in lib.classes) {
        _topologicalSortVisit(class_, new Set<Class>(),
            orderedList: addedClassesSorted);
      }
      knownLibraries.add(lib);
    }
    for (_ClassInfo info in changedClasses) {
      _topologicalSortVisit(info.classNode, new Set<Class>(),
          orderedList: addedClassesSorted);
    }
    _initializeTopologicallySortedClasses(
        addedClassesSorted, expectedStartIndex);

    assert(sanityChecks());

    return this;
  }

  @override
  ClassHierarchy applyMemberChanges(Iterable<Class> classes,
      {bool findDescendants = false}) {
    if (classes.isEmpty) return this;

    List<_ClassInfo> infos = <_ClassInfo>[];
    if (findDescendants) {
      Set<_ClassInfo> processedClasses = new Set<_ClassInfo>();
      List<_ClassInfo> worklist = <_ClassInfo>[];
      for (Class class_ in classes) {
        _ClassInfo info = infoFor(class_);
        worklist.add(info);
      }

      while (worklist.isNotEmpty) {
        _ClassInfo info = worklist.removeLast();
        if (processedClasses.add(info)) {
          worklist.addAll(info.directExtenders);
          worklist.addAll(info.directImplementers);
          worklist.addAll(info.directMixers);
        }
      }
      infos.addAll(processedClasses);
    } else {
      for (Class class_ in classes) {
        _ClassInfo info = infoFor(class_);
        infos.add(info);
      }
    }

    for (_ClassInfo info in infos) {
      info.lazyDeclaredGettersAndCalls = null;
      info.lazyDeclaredSetters = null;
      info.lazyImplementedGettersAndCalls = null;
      info.lazyImplementedSetters = null;
      info.lazyInterfaceGettersAndCalls = null;
      info.lazyInterfaceSetters = null;
    }
    assert(sanityChecks());

    return this;
  }

  bool sanityChecks() {
    Map<String, List<Class>> map = {};
    for (Class c in _infoMap.keys) {
      String className = "${c.enclosingLibrary.importUri}::${c.name}";
      List<Class>? list = map[className];
      if (list == null) {
        map[className] = list = [];
      }
      list.add(c);
    }

    StringBuffer? sb;
    for (MapEntry<String, List<Class>> entry in map.entries) {
      if (entry.value.length != 1) {
        sb ??= new StringBuffer();
        sb.writeln("Found ${entry.value.length} entries for ${entry.key}");
      }
    }
    if (sb != null) throw new StateError(sb.toString());

    for (Class c in _infoMap.keys) {
      if (!knownLibraries.contains(c.enclosingLibrary)) {
        throw new StateError("Didn't know library of $c (from ${c.fileUri})");
      }
    }

    for (_ClassInfo info in _infoMap.values) {
      for (_ClassInfo subInfo in info.directExtenders) {
        if (!_infoMap.containsKey(subInfo.classNode)) {
          throw new StateError(
              "Found $subInfo (${subInfo.classNode}) in directExtenders");
        }
      }
      for (_ClassInfo subInfo in info.directMixers) {
        if (!_infoMap.containsKey(subInfo.classNode)) {
          throw new StateError(
              "Found $subInfo (${subInfo.classNode}) in directMixers");
        }
      }
      for (_ClassInfo subInfo in info.directImplementers) {
        if (!_infoMap.containsKey(subInfo.classNode)) {
          throw new StateError(
              "Found $subInfo (${subInfo.classNode}) in directImplementers");
        }
      }
    }
    return true;
  }

  void _initialize(List<Library> libraries) {
    // Build the class ordering based on a topological sort.
    for (Library library in libraries) {
      for (Class classNode in library.classes) {
        _topologicalSortVisit(classNode, new Set<Class>());
      }
      knownLibraries.add(library);
    }

    _initializeTopologicallySortedClasses(_infoMap.keys, 0);
  }

  /// - Build index of direct children.
  /// - Build list of super classes and super types.
  /// - Infer and record supertypes for the classes.
  /// - Record interface members.
  /// - Perform some sanity checking.
  /// Do this after the topological sort so that super types always occur
  /// before subtypes.
  void _initializeTopologicallySortedClasses(
      Iterable<Class> classes, int expectedStartingTopologicalIndex) {
    int i = expectedStartingTopologicalIndex;
    for (Class class_ in classes) {
      _ClassInfo? info = _infoMap[class_];
      if (info == null) {
        throw "No info for ${class_.name} from ${class_.fileUri}.";
      }

      if (class_.supertype != null) {
        _infoMap[class_.supertype!.classNode]!.directExtenders.add(info);
      }
      if (class_.mixedInType != null) {
        _infoMap[class_.mixedInType!.classNode]!.directMixers.add(info);
      }
      for (Supertype supertype in class_.implementedTypes) {
        _infoMap[supertype.classNode]!.directImplementers.add(info);
      }
      _collectSupersForClass(class_);

      Supertype? supertype = class_.supertype;
      if (supertype != null) {
        _recordSuperTypes(info, supertype);
      }
      Supertype? mixedInType = class_.mixedInType;
      if (mixedInType != null) {
        _recordSuperTypes(info, mixedInType);
      }
      for (Supertype supertype in class_.implementedTypes) {
        _recordSuperTypes(info, supertype);
      }

      if (info.topologicalIndex != i) {
        throw "Unexpected topologicalIndex (${info.topologicalIndex} != $i) "
            "for ${class_.name} from ${class_.fileUri}.";
      }
      i++;
    }
  }

  /// Upwards traversal of the class hierarchy that orders classes so super
  /// types before their subtypes.
  ///
  /// Returns the depth of the visited class (the number of steps in the longest
  /// inheritance path to the root class).
  int _topSortIndex = 0;
  int _topologicalSortVisit(Class classNode, Set<Class> beingVisited,
      {List<Class>? orderedList}) {
    _ClassInfo? info = _infoMap[classNode];
    if (info != null) {
      return info.depth;
    }

    if (!beingVisited.add(classNode)) {
      throw 'Cyclic inheritance involving ${classNode.name}';
    }

    info = new _ClassInfo(classNode);

    int superDepth = -1;
    if (classNode.supertype != null) {
      superDepth = max(
          superDepth,
          _topologicalSortVisit(classNode.supertype!.classNode, beingVisited,
              orderedList: orderedList));
    }
    if (classNode.mixedInType != null) {
      superDepth = max(
          superDepth,
          _topologicalSortVisit(classNode.mixedInType!.classNode, beingVisited,
              orderedList: orderedList));
    }
    for (Supertype supertype in classNode.implementedTypes) {
      superDepth = max(
          superDepth,
          _topologicalSortVisit(supertype.classNode, beingVisited,
              orderedList: orderedList));
    }

    info.topologicalIndex = _topSortIndex++;

    _infoMap[classNode] = info;
    orderedList?.add(classNode);
    beingVisited.remove(classNode);
    return info.depth = superDepth + 1;
  }

  List<Member> _buildImplementedMembers(Class classNode, _ClassInfo info,
      {required bool setters}) {
    List<Member>? members = setters
        ? info.lazyImplementedSetters
        : info.lazyImplementedGettersAndCalls;
    if (members != null) return members;

    List<Member> inherited;
    Supertype? supertype = classNode.supertype;
    if (supertype == null) {
      inherited = const <Member>[];
    } else {
      Class superClassNode = supertype.classNode;
      _ClassInfo superInfo = _infoMap[superClassNode]!;
      inherited =
          _buildImplementedMembers(superClassNode, superInfo, setters: setters);
    }
    members = _inheritMembers(
        _buildDeclaredMembers(classNode, info, setters: setters), inherited,
        skipAbstractMembers: true);
    if (setters) {
      info.lazyImplementedSetters = members;
    } else {
      info.lazyImplementedGettersAndCalls = members;
    }
    return members;
  }

  List<Member> _buildDeclaredMembers(Class classNode, _ClassInfo info,
      {required bool setters}) {
    List<Member>? members =
        setters ? info.lazyDeclaredSetters : info.lazyDeclaredGettersAndCalls;
    if (members != null) return members;

    // To support that mixin application can declare their own members, for
    // instance cloned mixin members and concrete forwarding stubs, we first
    // collect the members in a map before creating the list of members, so that
    // declared members can replace mixed in members.
    Map<Name, Member> memberMap = {};
    if (classNode.mixedInType != null) {
      Class mixedInClassNode = classNode.mixedInType!.classNode;
      _ClassInfo mixedInInfo = _infoMap[mixedInClassNode]!;

      for (Member mixinMember in _buildDeclaredMembers(
          mixedInClassNode, mixedInInfo,
          setters: setters)) {
        if (mixinMember is! Procedure || !mixinMember.isSynthetic) {
          memberMap[mixinMember.name] = mixinMember;
        }
      }
    }

    for (Procedure procedure in classNode.procedures) {
      if (procedure.isStatic) continue;
      if (procedure.kind == ProcedureKind.Setter) {
        if (setters) {
          memberMap[procedure.name] = procedure;
        }
      } else {
        if (!setters) {
          memberMap[procedure.name] = procedure;
        }
      }
    }
    for (Field field in classNode.fields) {
      if (field.isStatic) continue;
      if (!setters) {
        memberMap[field.name] = field;
      }
      if (setters && field.hasSetter) {
        memberMap[field.name] = field;
      }
    }

    members = memberMap.values.toList();
    members.sort(ClassHierarchy.compareMembers);

    if (setters) {
      info.lazyDeclaredSetters = members;
    } else {
      info.lazyDeclaredGettersAndCalls = members;
    }
    return members;
  }

  List<Member> _buildInterfaceMembers(Class classNode, _ClassInfo info,
      {required bool setters}) {
    List<Member>? members =
        setters ? info.lazyInterfaceSetters : info.lazyInterfaceGettersAndCalls;
    if (members != null) return members;
    List<Member> allInheritedMembers = <Member>[];
    List<Member> declared =
        _buildDeclaredMembers(classNode, info, setters: setters);

    void inheritFrom(Supertype? type) {
      if (type == null) return;
      List<Member> inherited = _buildInterfaceMembers(
          type.classNode, _infoMap[type.classNode]!,
          setters: setters);
      inherited = _getUnshadowedInheritedMembers(declared, inherited);
      allInheritedMembers =
          ClassHierarchy.mergeSortedLists(allInheritedMembers, inherited);
    }

    inheritFrom(classNode.supertype);
    inheritFrom(classNode.mixedInType);
    classNode.implementedTypes.forEach(inheritFrom);
    members = _inheritMembers(declared, allInheritedMembers);
    if (setters) {
      info.lazyInterfaceSetters = members;
    } else {
      info.lazyInterfaceGettersAndCalls = members;
    }
    return members;
  }

  /// Computes the list of implemented members, based on the declared instance
  /// members and inherited instance members.
  ///
  /// Both lists must be sorted by name beforehand.
  static List<Member> _inheritMembers(
      List<Member> declared, List<Member> inherited,
      {bool skipAbstractMembers = false}) {
    List<Member> result = new List<Member>.filled(
        declared.length + inherited.length, dummyMember,
        growable: true);
    // Since both lists are sorted, we can fuse them like in merge sort.
    int storeIndex = 0;
    int i = 0, j = 0;
    while (i < declared.length && j < inherited.length) {
      Member declaredMember = declared[i];
      Member inheritedMember = inherited[j];
      if (skipAbstractMembers && declaredMember.isAbstract) {
        ++i;
        continue;
      }
      if (skipAbstractMembers && inheritedMember.isAbstract) {
        ++j;
        continue;
      }
      int comparison =
          ClassHierarchy.compareMembers(declaredMember, inheritedMember);
      if (comparison < 0) {
        result[storeIndex++] = declaredMember;
        ++i;
      } else if (comparison > 0) {
        result[storeIndex++] = inheritedMember;
        ++j;
      } else {
        result[storeIndex++] = declaredMember;
        ++i;
        ++j; // Move past overridden member.
      }
    }
    // One of the two lists is now exhausted, copy over the remains.
    while (i < declared.length) {
      Member declaredMember = declared[i++];
      if (skipAbstractMembers && declaredMember.isAbstract) continue;
      result[storeIndex++] = declaredMember;
    }
    while (j < inherited.length) {
      Member inheritedMember = inherited[j++];
      if (skipAbstractMembers && inheritedMember.isAbstract) continue;
      result[storeIndex++] = inheritedMember;
    }
    result.length = storeIndex;
    return result;
  }

  /// Returns the subset of members in [inherited] for which a member with the
  /// same name does not occur in [declared].
  ///
  /// The input lists must be sorted, and the returned list is sorted.
  static List<Member> _getUnshadowedInheritedMembers(
      List<Member> declared, List<Member> inherited) {
    List<Member> result =
        new List<Member>.filled(inherited.length, dummyMember, growable: true);
    int storeIndex = 0;
    int i = 0, j = 0;
    while (i < declared.length && j < inherited.length) {
      Member declaredMember = declared[i];
      Member inheritedMember = inherited[j];
      int comparison =
          ClassHierarchy.compareMembers(declaredMember, inheritedMember);
      if (comparison < 0) {
        ++i;
      } else if (comparison > 0) {
        result[storeIndex++] = inheritedMember;
        ++j;
      } else {
        // Move past the shadowed member, but retain the declared member, as
        // it may shadow multiple members.
        ++j;
      }
    }
    // If the list of declared members is exhausted, copy over the remains of
    // the inherited members.
    while (j < inherited.length) {
      result[storeIndex++] = inherited[j++];
    }
    result.length = storeIndex;
    return result;
  }

  void _recordSuperTypes(_ClassInfo subInfo, Supertype supertype) {
    _ClassInfo superInfo = _infoMap[supertype.classNode]!;
    if (supertype.typeArguments.isEmpty) {
      if (superInfo.genericSuperTypes == null) return;
      // Copy over the super type entries.
      subInfo.genericSuperType ??= <Class, Supertype>{};
      subInfo.genericSuperTypes ??= <Class, List<Supertype>>{};
      superInfo.genericSuperType?.forEach((Class key, Supertype type) {
        subInfo.recordGenericSuperType(
            coreTypes, key, type, _onAmbiguousSupertypes);
      });
    } else {
      // Copy over all transitive generic super types, and substitute the
      // free variables with those provided in [supertype].
      Class superclass = supertype.classNode;
      Substitution substitution = Substitution.fromPairs(
          superclass.typeParameters, supertype.typeArguments);
      subInfo.genericSuperType ??= <Class, Supertype>{};
      subInfo.genericSuperTypes ??= <Class, List<Supertype>>{};
      superInfo.genericSuperType?.forEach((Class key, Supertype type) {
        subInfo.recordGenericSuperType(coreTypes, key,
            substitution.substituteSupertype(type), _onAmbiguousSupertypes);
      });

      subInfo.recordGenericSuperType(
          coreTypes, superclass, supertype, _onAmbiguousSupertypes);
    }
  }

  /// Build lists of super types and super classes.
  /// Note that the super class and super types of the class must already have
  /// had their supers collected.
  void _collectSupersForClass(Class class_) {
    _ClassInfo info = _infoMap[class_]!;

    _IntervalListBuilder superclassSetBuilder = new _IntervalListBuilder()
      ..addSingleton(info.topologicalIndex);
    _IntervalListBuilder supertypeSetBuilder = new _IntervalListBuilder()
      ..addSingleton(info.topologicalIndex);

    if (class_.supertype != null) {
      _ClassInfo supertypeInfo = _infoMap[class_.supertype!.classNode]!;
      superclassSetBuilder
          .addIntervalList(supertypeInfo.superclassIntervalList);
      supertypeSetBuilder.addIntervalList(supertypeInfo.supertypeIntervalList);
    }

    if (class_.mixedInType != null) {
      _ClassInfo mixedInTypeInfo = _infoMap[class_.mixedInType!.classNode]!;
      supertypeSetBuilder
          .addIntervalList(mixedInTypeInfo.supertypeIntervalList);
    }

    for (Supertype supertype in class_.implementedTypes) {
      _ClassInfo supertypeInfo = _infoMap[supertype.classNode]!;
      supertypeSetBuilder.addIntervalList(supertypeInfo.supertypeIntervalList);
    }

    info.superclassIntervalList = superclassSetBuilder.buildIntervalList();
    info.supertypeIntervalList = supertypeSetBuilder.buildIntervalList();
  }

  /// Creates a histogram such that index `N` contains the number of classes
  /// that have `N` intervals in its supertype set.
  ///
  /// The more numbers are condensed near the beginning, the more efficient the
  /// internal data structure is.
  List<int> getExpenseHistogram() {
    List<int> result = <int>[];
    for (Class class_ in _infoMap.keys) {
      _ClassInfo info = _infoMap[class_]!;
      int intervals = info.supertypeIntervalList.length ~/ 2;
      while (result.length <= intervals) {
        result.add(0);
      }
      result[intervals] += 1;
    }
    return result;
  }

  /// Returns the average number of intervals per supertype relation (less
  /// is better, 1.0 is bad).
  ///
  /// This is an estimate of the memory use compared to a data structure that
  /// enumerates all superclass/supertype pairs.
  double getCompressionRatio() {
    int intervals = 0;
    int sizes = 0;
    for (Class class_ in _infoMap.keys) {
      _ClassInfo info = _infoMap[class_]!;
      intervals += (info.superclassIntervalList.length +
              info.supertypeIntervalList.length) ~/
          2;
      sizes += _intervalListSize(info.superclassIntervalList) +
          _intervalListSize(info.supertypeIntervalList);
    }

    return sizes == 0 ? 1.0 : intervals / sizes;
  }

  /// Returns the number of entries in hash tables storing hierarchy data.
  int getSuperTypeHashTableSize() {
    int sum = 0;
    for (Class class_ in _infoMap.keys) {
      sum += _infoMap[class_]!.genericSuperTypes?.length ?? 0;
    }
    return sum;
  }
}

class _IntervalListBuilder {
  final List<int> events = <int>[];

  void addInterval(int start, int end) {
    // Add an event point for each interval end point, using the low bit to
    // distinguish opening from closing end points. Closing end points should
    // have the high bit to ensure they occur after an opening end point.
    events.add(start << 1);
    events.add((end << 1) + 1);
  }

  void addSingleton(int x) {
    addInterval(x, x + 1);
  }

  void addIntervalList(Uint32List intervals) {
    for (int i = 0; i < intervals.length; i += 2) {
      addInterval(intervals[i], intervals[i + 1]);
    }
  }

  Uint32List buildIntervalList() {
    // Sort the event points and sweep left to right while tracking how many
    // intervals we are currently inside.  Record an interval end point when the
    // number of intervals drop to zero or increase from zero to one.
    // Event points are encoded so that an opening end point occur before a
    // closing end point at the same value.
    events.sort();
    int insideCount = 0; // The number of intervals we are currently inside.
    int storeIndex = 0;
    for (int i = 0; i < events.length; ++i) {
      int event = events[i];
      if (event & 1 == 0) {
        // Start point
        ++insideCount;
        if (insideCount == 1) {
          // Store the results temporarily back in the event array.
          events[storeIndex++] = event >> 1;
        }
      } else {
        // End point
        --insideCount;
        if (insideCount == 0) {
          events[storeIndex++] = event >> 1;
        }
      }
    }
    // Copy the results over to a typed array of the correct length.
    Uint32List result = new Uint32List(storeIndex);
    for (int i = 0; i < storeIndex; ++i) {
      result[i] = events[i];
    }
    return result;
  }
}

bool _intervalListContains(Uint32List intervalList, int x) {
  int low = 0, high = intervalList.length - 1;
  if (high == -1 || x < intervalList[0] || intervalList[high] <= x) {
    return false;
  }
  // Find the lower bound of x in the list.
  // If the lower bound is at an even index, the lower bound is an opening point
  // of an interval that contains x, otherwise it is a closing point of an
  // interval below x and there is no interval containing x.
  while (low < high) {
    int mid = high - ((high - low) >> 1); // Get middle, rounding up.
    int pivot = intervalList[mid];
    if (pivot <= x) {
      low = mid;
    } else {
      high = mid - 1;
    }
  }
  return low == high && (low & 1) == 0;
}

int _intervalListSize(Uint32List intervalList) {
  int size = 0;
  for (int i = 0; i < intervalList.length; i += 2) {
    size += intervalList[i + 1] - intervalList[i];
  }
  return size;
}

class ForTestingClassInfo {
  final Class classNode;
  final List<Member>? lazyDeclaredGettersAndCalls;
  final List<Member>? lazyDeclaredSetters;
  final List<Member>? lazyImplementedGettersAndCalls;
  final List<Member>? lazyImplementedSetters;
  final List<Member>? lazyInterfaceGettersAndCalls;
  final List<Member>? lazyInterfaceSetters;

  ForTestingClassInfo._(_ClassInfo c)
      : classNode = c.classNode,
        lazyDeclaredGettersAndCalls = c.lazyDeclaredGettersAndCalls,
        lazyDeclaredSetters = c.lazyDeclaredSetters,
        lazyImplementedGettersAndCalls = c.lazyImplementedGettersAndCalls,
        lazyImplementedSetters = c.lazyImplementedSetters,
        lazyInterfaceGettersAndCalls = c.lazyInterfaceGettersAndCalls,
        lazyInterfaceSetters = c.lazyInterfaceSetters;
}

class _ClassInfo {
  bool used = false;
  final Class classNode;
  int topologicalIndex = 0;
  int depth = 0;

  // Super types must always occur before subtypes in these lists.
  // For example:
  //
  //   class A extends Object
  //   class B extends Object implements A
  //
  // Here `A` must occur before `B` in the list of direct extenders of Object,
  // because `B` is a subtype of `A`.
  final Set<_ClassInfo> directExtenders = new LinkedHashSet<_ClassInfo>();
  final Set<_ClassInfo> directMixers = new LinkedHashSet<_ClassInfo>();
  final Set<_ClassInfo> directImplementers = new LinkedHashSet<_ClassInfo>();

  late final Uint32List superclassIntervalList;
  late final Uint32List supertypeIntervalList;

  List<_ClassInfo>? leastUpperBoundInfos;

  /// Maps generic supertype classes to the instantiations implemented by this
  /// class.
  ///
  /// E.g. `List` maps to `List<String>` for a class that directly or indirectly
  /// implements `List<String>`.
  Map<Class, List<Supertype>>? genericSuperTypes;

  /// Maps generic supertype classes to the canonical instantiation implemented
  /// by this class.
  ///
  /// E.g. `List` maps to `List<String>` for a class that directly or indirectly
  /// implements `List<String>`.

  Map<Class, Supertype>? genericSuperType;

  /// Instance fields, getters, methods, and operators declared in this class
  /// or its mixed-in class, sorted according to [_compareMembers].
  List<Member>? lazyDeclaredGettersAndCalls;

  /// Non-final instance fields and setters declared in this class or its
  /// mixed-in class, sorted according to [_compareMembers].
  List<Member>? lazyDeclaredSetters;

  /// Instance fields, getters, methods, and operators implemented by this class
  /// (declared or inherited).
  List<Member>? lazyImplementedGettersAndCalls;

  /// Non-final instance fields and setters implemented by this class
  /// (declared or inherited).
  List<Member>? lazyImplementedSetters;

  List<Member>? lazyInterfaceGettersAndCalls;
  List<Member>? lazyInterfaceSetters;

  _ClassInfo(this.classNode);

  bool isSubclassOf(_ClassInfo other) {
    return _intervalListContains(
        superclassIntervalList, other.topologicalIndex);
  }

  bool isSubtypeOf(_ClassInfo other) {
    return _intervalListContains(supertypeIntervalList, other.topologicalIndex);
  }

  void recordGenericSuperType(CoreTypes coreTypes, Class cls, Supertype type,
      HandleAmbiguousSupertypes onAmbiguousSupertypes) {
    Supertype? canonical = genericSuperType![cls];
    if (canonical == null) {
      canonical = type;
      genericSuperType![cls] = canonical;
      genericSuperTypes![cls] = <Supertype>[type];
    } else {
      genericSuperTypes![cls]!.add(type);

      Supertype? result = nnbdTopMergeSupertype(coreTypes,
          normSupertype(coreTypes, type), normSupertype(coreTypes, canonical));
      if (result == null) {
        onAmbiguousSupertypes(classNode, canonical, type);
      } else {
        genericSuperType![cls] = result;
      }
    }
    assert(genericSuperType!.containsKey(cls),
        "No canonical instantiation computed for $cls in $classNode.");
    assert(genericSuperTypes!.containsKey(cls),
        "No instantiations computed for $cls in $classNode.");
  }
}

/// An immutable set of classes.
class ClassSet extends IterableBase<Class> {
  final Set<Class> _classes;
  ClassSet(this._classes);

  @override
  bool contains(Object? class_) {
    return _classes.contains(class_);
  }

  @override
  Iterator<Class> get iterator => _classes.iterator;
}

/// Heap for use in computing least upper bounds.
///
/// The heap is sorted such that classes that are deepest in the hierarchy
/// are removed first; in the case of ties, classes with lower topological sort
/// index are removed first.
class _LubHeap extends Heap<_ClassInfo> {
  @override
  bool sortsBefore(_ClassInfo a, _ClassInfo b) => sortsBeforeStatic(a, b);

  static bool sortsBeforeStatic(_ClassInfo a, _ClassInfo b) {
    if (a.depth > b.depth) return true;
    if (a.depth < b.depth) return false;
    return a.topologicalIndex < b.topologicalIndex;
  }
}
