// 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/legacy_erasure.dart';
import 'src/nnbd_top_merge.dart';
import 'src/norm.dart';

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

abstract class MixinInferrer {
  void infer(ClassHierarchy hierarchy, Class classNode);
}

/// 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 [superclass] that is implemented by [type],
  /// or `null` if [type] does not implement [superclass] at all.
  InterfaceType? getTypeAsInstanceOf(
      InterfaceType type, Class superclass, Library clientLibrary);

  /// 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>? getTypeArgumentsAsInstanceOf(
      InterfaceType type, Class superclass);

  /// True if [subtype] inherits from [superclass] though zero or more
  /// `extends`, `with`, and `implements` relationships.
  bool isSubtypeOf(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, Library clientLibrary);
}

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,
      MixinInferrer? mixinInferrer}) {
    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, mixinInferrer)
      .._initialize(component.libraries);
  }

  void set coreTypes(CoreTypes coreTypes);

  void set onAmbiguousSupertypes(
      HandleAmbiguousSupertypes onAmbiguousSupertypes);

  void set mixinInferrer(MixinInferrer mixinInferrer);

  /// 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 instantiation of each generic supertype implemented by this
  // class (e.g. getClassAsInstanceOf applied to all superclasses and
  // interfaces).
  List<Supertype> genericSupertypesOf(Class class_);

  /// Returns the instantiation of [superclass] that is implemented by [type],
  /// or `null` if [type] does not implement [superclass].  [superclass] must
  /// be a generic class.
  Supertype? asInstantiationOf(Supertype type, Class superclass);

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

  /// True if the given class is used as the right-hand operand to a
  /// mixin application (i.e. [Class.mixedInType]).
  bool isUsedAsMixin(Class class_);

  /// True if the given class is extended by another class using `extends`.
  bool isExtended(Class class_);

  /// 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) {
      // ignore: unnecessary_null_comparison
      if (firstLibrary == null) return -1;
      // ignore: unnecessary_null_comparison
      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 implements ClassHierarchy {
  @override
  CoreTypes coreTypes;
  late HandleAmbiguousSupertypes _onAmbiguousSupertypes;
  late HandleAmbiguousSupertypes _onAmbiguousSupertypesNotWrapped;
  MixinInferrer? mixinInferrer;

  @override
  void set onAmbiguousSupertypes(
      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);
    };
  }

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

  int get numberOfClasses {
    allBetsOff = true;
    return _infoMap.length;
  }

  _ClosedWorldClassHierarchySubtypes? _cachedClassHierarchySubtypes;

  ClosedWorldClassHierarchy._internal(this.coreTypes,
      HandleAmbiguousSupertypes onAmbiguousSupertypes, this.mixinInferrer) {
    this.onAmbiguousSupertypes = onAmbiguousSupertypes;
  }

  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 isSubtypeOf(Class subtype, Class superclass) {
    if (identical(subtype, superclass)) return true;
    return infoFor(subtype).isSubtypeOf(infoFor(superclass));
  }

  @override
  bool isUsedAsMixin(Class class_) {
    return infoFor(class_).directMixers.isNotEmpty;
  }

  @override
  bool isExtended(Class class_) {
    return infoFor(class_).directExtenders.isNotEmpty;
  }

  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;
  }

  @override
  InterfaceType getLegacyLeastUpperBound(
      InterfaceType type1, InterfaceType type2, Library clientLibrary) {
    // 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.

    // LLUB(Null, List<dynamic>*) works differently for opt-in and opt-out
    // libraries.  In opt-out libraries the legacy behavior is preserved, so
    // LLUB(Null, List<dynamic>*) = List<dynamic>*.  In opt-in libraries the
    // rules imply that LLUB(Null, List<dynamic>*) = List<dynamic>?.
    if (!clientLibrary.isNonNullableByDefault) {
      if (type1 is NullType) return type2;
      if (type2 is NullType) return type1;
    }

    _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);
    }

    // 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 = classes1[i1];
      _ClassInfo next2 = classes2[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 = identical(info1, next)
            ? type1
            : Substitution.fromInterfaceType(type1).substituteType(
                    info1.genericSuperType![next.classNode]!.asInterfaceType)
                as InterfaceType;
        InterfaceType superType2 = identical(info2, next)
            ? type2
            : Substitution.fromInterfaceType(type2).substituteType(
                    info2.genericSuperType![next.classNode]!.asInterfaceType)
                as InterfaceType;
        if (!clientLibrary.isNonNullableByDefault) {
          superType1 = legacyErasure(superType1) as InterfaceType;
          superType2 = legacyErasure(superType2) as InterfaceType;
        }
        if (superType1 == superType2) {
          candidate = superType1.withDeclaredNullability(
              uniteNullabilities(type1.nullability, type2.nullability));
          ++numCandidatesAtThisDepth;
        }
      }
    }
  }

  @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? getTypeAsInstanceOf(
      InterfaceType type, Class superclass, Library clientLibrary) {
    List<DartType>? typeArguments =
        getTypeArgumentsAsInstanceOf(type, superclass);
    if (typeArguments == null) return null;
    // The return value should be a legacy type if it's computed for an
    // opted-out library, unless the return value is Null? which is always
    // nullable.
    Nullability nullability = clientLibrary.isNonNullableByDefault
        ? type.nullability
        : Nullability.legacy;
    return new InterfaceType(superclass, nullability, typeArguments);
  }

  @override
  List<DartType>? getTypeArgumentsAsInstanceOf(
      InterfaceType type, Class superclass) {
    if (type.classNode == superclass) {
      // 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;
      }
    }
  }

  @override
  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;
  }

  @override
  Supertype? asInstantiationOf(Supertype type, Class superclass) {
    // This is similar to getTypeAsInstanceOf, except that it assumes that
    // superclass is a generic class.  It thus does not rely on being able
    // to answer isSubtypeOf queries and so can be used before we have built
    // the intervals needed for those queries.
    assert(superclass.typeParameters.isNotEmpty);
    if (type.classNode == superclass) {
      return superclass.asThisSupertype;
    }
    Map<Class, Supertype>? map = infoFor(type.classNode).genericSuperType;
    return map == null ? null : map[superclass];
  }

  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) {
        mixinInferrer?.infer(this, class_);
        _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) {
      if (!classNode.enclosingLibrary.isNonNullableByDefault) {
        canonical = legacyErasureSupertype(type);
      } else {
        canonical = type;
      }
      // ignore: unnecessary_null_comparison
      assert(canonical != null,
          "No canonical instantiation computed for $cls in $classNode.");
      genericSuperType![cls] = canonical;
      genericSuperTypes![cls] = <Supertype>[type];
    } else {
      genericSuperTypes![cls]!.add(type);

      if (classNode.enclosingLibrary.isNonNullableByDefault) {
        Supertype? result = nnbdTopMergeSupertype(
            coreTypes,
            normSupertype(coreTypes, type),
            normSupertype(coreTypes, canonical));
        if (result == null) {
          onAmbiguousSupertypes(classNode, canonical, type);
        } else {
          genericSuperType![cls] = result;
        }
      } else {
        type = legacyErasureSupertype(type);
        if (type != canonical) {
          onAmbiguousSupertypes(classNode, canonical, type);
        }
      }
    }
    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_);
  }

  ClassSet union(ClassSet other) {
    Set<Class> result = new Set<Class>.of(_classes);
    result.addAll(other._classes);
    return new ClassSet(result);
  }

  @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;
  }
}
