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

library fasta.class_hierarchy_builder;

import 'package:kernel/ast.dart';

import 'package:kernel/class_hierarchy.dart'
    show ClassHierarchy, ClassHierarchyBase;

import 'package:kernel/core_types.dart' show CoreTypes;

import 'package:kernel/type_algebra.dart' show Substitution, uniteNullabilities;
import 'package:kernel/type_environment.dart';

import 'package:kernel/src/legacy_erasure.dart';
import 'package:kernel/src/nnbd_top_merge.dart';
import 'package:kernel/src/norm.dart';
import 'package:kernel/src/standard_bounds.dart';
import 'package:kernel/src/types.dart' show Types;

import '../../base/common.dart';
import '../../testing/id_testing_utils.dart' show typeToText;

import '../builder/builder.dart';
import '../builder/class_builder.dart';
import '../builder/field_builder.dart';
import '../builder/formal_parameter_builder.dart';
import '../builder/library_builder.dart';
import '../builder/member_builder.dart';
import '../builder/named_type_builder.dart';
import '../builder/procedure_builder.dart';
import '../builder/type_alias_builder.dart';
import '../builder/type_builder.dart';
import '../builder/type_declaration_builder.dart';

import '../loader.dart' show Loader;

import '../messages.dart'
    show
        LocatedMessage,
        Message,
        messageDeclaredMemberConflictsWithInheritedMember,
        messageDeclaredMemberConflictsWithInheritedMemberCause,
        messageDeclaredMemberConflictsWithOverriddenMembersCause,
        messageInheritedMembersConflict,
        messageInheritedMembersConflictCause1,
        messageInheritedMembersConflictCause2,
        messageStaticAndInstanceConflict,
        messageStaticAndInstanceConflictCause,
        templateCantInferTypesDueToNoCombinedSignature,
        templateCantInferReturnTypeDueToNoCombinedSignature,
        templateCantInferTypeDueToNoCombinedSignature,
        templateCombinedMemberSignatureFailed,
        templateDuplicatedDeclaration,
        templateDuplicatedDeclarationCause,
        templateMissingImplementationCause,
        templateMissingImplementationNotAbstract;

import '../names.dart' show noSuchMethodName;

import '../scope.dart' show Scope;

import '../source/source_class_builder.dart';
import '../source/source_library_builder.dart' show SourceLibraryBuilder;

import '../source/source_loader.dart' show SourceLoader;

import '../type_inference/standard_bounds.dart' show TypeSchemaStandardBounds;

import '../type_inference/type_constraint_gatherer.dart'
    show TypeConstraintGatherer;

import '../type_inference/type_inferrer.dart' show MixinInferrer;

import '../type_inference/type_schema.dart' show UnknownType;

import '../type_inference/type_schema_environment.dart' show TypeConstraint;

import 'combined_member_signature.dart';

import 'member_covariance.dart';

import 'forwarding_node.dart' show ForwardingNode;

const DebugLogger? debug =
    const bool.fromEnvironment("debug.hierarchy") ? const DebugLogger() : null;

class DebugLogger {
  const DebugLogger();
  void log(Object message) => print(message);
}

int compareDeclarations(ClassMember a, ClassMember b) {
  if (a == b) return 0;
  return ClassHierarchy.compareNames(a.name, b.name);
}

int compareClassMembers(ClassMember a, ClassMember b) {
  if (a.forSetter == b.forSetter) {
    return compareDeclarations(a, b);
  } else if (a.forSetter) {
    return 1;
  } else {
    return -1;
  }
}

bool isNameVisibleIn(Name name, LibraryBuilder libraryBuilder) {
  return !name.isPrivate || name.library == libraryBuilder.library;
}

class Tuple {
  final Name name;
  ClassMember? _declaredMember;
  ClassMember? _declaredSetter;
  ClassMember? _mixedInMember;
  ClassMember? _mixedInSetter;
  ClassMember? _extendedMember;
  ClassMember? _extendedSetter;
  List<ClassMember>? _implementedMembers;
  List<ClassMember>? _implementedSetters;

  Tuple.declareMember(ClassMember declaredMember)
      : assert(!declaredMember.forSetter),
        this._declaredMember = declaredMember,
        this.name = declaredMember.name;

  Tuple.mixInMember(ClassMember mixedInMember)
      : assert(!mixedInMember.forSetter),
        this._mixedInMember = mixedInMember,
        this.name = mixedInMember.name;

  Tuple.extendMember(ClassMember extendedMember)
      : assert(!extendedMember.forSetter),
        this._extendedMember = extendedMember,
        this.name = extendedMember.name;

  Tuple.implementMember(ClassMember implementedMember)
      : assert(!implementedMember.forSetter),
        this.name = implementedMember.name,
        _implementedMembers = <ClassMember>[implementedMember];

  Tuple.declareSetter(ClassMember declaredSetter)
      : assert(declaredSetter.forSetter),
        this._declaredSetter = declaredSetter,
        this.name = declaredSetter.name;

  Tuple.mixInSetter(ClassMember mixedInSetter)
      : assert(mixedInSetter.forSetter),
        this._mixedInSetter = mixedInSetter,
        this.name = mixedInSetter.name;

  Tuple.extendSetter(ClassMember extendedSetter)
      : assert(extendedSetter.forSetter),
        this._extendedSetter = extendedSetter,
        this.name = extendedSetter.name;

  Tuple.implementSetter(ClassMember implementedSetter)
      : assert(implementedSetter.forSetter),
        this.name = implementedSetter.name,
        _implementedSetters = <ClassMember>[implementedSetter];

  ClassMember? get declaredMember => _declaredMember;

  void set declaredMember(ClassMember? value) {
    assert(!value!.forSetter);
    assert(
        _declaredMember == null,
        "Declared member already set to $_declaredMember, "
        "trying to set it to $value.");
    _declaredMember = value;
  }

  ClassMember? get declaredSetter => _declaredSetter;

  void set declaredSetter(ClassMember? value) {
    assert(value!.forSetter);
    assert(
        _declaredSetter == null,
        "Declared setter already set to $_declaredSetter, "
        "trying to set it to $value.");
    _declaredSetter = value;
  }

  ClassMember? get extendedMember => _extendedMember;

  void set extendedMember(ClassMember? value) {
    assert(!value!.forSetter);
    assert(
        _extendedMember == null,
        "Extended member already set to $_extendedMember, "
        "trying to set it to $value.");
    _extendedMember = value;
  }

  ClassMember? get extendedSetter => _extendedSetter;

  void set extendedSetter(ClassMember? value) {
    assert(value!.forSetter);
    assert(
        _extendedSetter == null,
        "Extended setter already set to $_extendedSetter, "
        "trying to set it to $value.");
    _extendedSetter = value;
  }

  ClassMember? get mixedInMember => _mixedInMember;

  void set mixedInMember(ClassMember? value) {
    assert(!value!.forSetter);
    assert(
        _mixedInMember == null,
        "Mixed in member already set to $_mixedInMember, "
        "trying to set it to $value.");
    _mixedInMember = value;
  }

  ClassMember? get mixedInSetter => _mixedInSetter;

  void set mixedInSetter(ClassMember? value) {
    assert(value!.forSetter);
    assert(
        _mixedInSetter == null,
        "Mixed in setter already set to $_mixedInSetter, "
        "trying to set it to $value.");
    _mixedInSetter = value;
  }

  List<ClassMember>? get implementedMembers => _implementedMembers;

  void addImplementedMember(ClassMember value) {
    assert(!value.forSetter);
    _implementedMembers ??= <ClassMember>[];
    _implementedMembers!.add(value);
  }

  List<ClassMember>? get implementedSetters => _implementedSetters;

  void addImplementedSetter(ClassMember value) {
    assert(value.forSetter);
    _implementedSetters ??= <ClassMember>[];
    _implementedSetters!.add(value);
  }

  @override
  String toString() {
    StringBuffer sb = new StringBuffer();
    String comma = '';
    sb.write('Tuple(');
    if (_declaredMember != null) {
      sb.write(comma);
      sb.write('declaredMember=');
      sb.write(_declaredMember);
      comma = ',';
    }
    if (_declaredSetter != null) {
      sb.write(comma);
      sb.write('declaredSetter=');
      sb.write(_declaredSetter);
      comma = ',';
    }
    if (_mixedInMember != null) {
      sb.write(comma);
      sb.write('mixedInMember=');
      sb.write(_mixedInMember);
      comma = ',';
    }
    if (_mixedInSetter != null) {
      sb.write(comma);
      sb.write('mixedInSetter=');
      sb.write(_mixedInSetter);
      comma = ',';
    }
    if (_extendedMember != null) {
      sb.write(comma);
      sb.write('extendedMember=');
      sb.write(_extendedMember);
      comma = ',';
    }
    if (_extendedSetter != null) {
      sb.write(comma);
      sb.write('extendedSetter=');
      sb.write(_extendedSetter);
      comma = ',';
    }
    if (_implementedMembers != null) {
      sb.write(comma);
      sb.write('implementedMembers=');
      sb.write(_implementedMembers);
      comma = ',';
    }
    if (_implementedSetters != null) {
      sb.write(comma);
      sb.write('implementedSetters=');
      sb.write(_implementedSetters);
      comma = ',';
    }
    sb.write(')');
    return sb.toString();
  }
}

abstract class ClassMember {
  Name get name;
  bool get isStatic;
  bool get isField;
  bool get isAssignable;
  bool get isSetter;
  bool get isGetter;
  bool get isFinal;
  bool get isConst;
  bool get forSetter;

  /// Returns `true` if this member corresponds to a declaration in the source
  /// code.
  bool get isSourceDeclaration;

  /// Returns `true` if this member is a field, getter or setter.
  bool get isProperty;

  /// Computes the [Member] node resulting from this class member.
  Member getMember(ClassHierarchyBuilder hierarchy);

  /// Returns the member [Covariance] for this class member.
  Covariance getCovariance(ClassHierarchyBuilder hierarchy);

  bool get isDuplicate;
  String get fullName;
  String get fullNameForErrors;
  ClassBuilder get classBuilder;

  /// Returns `true` if this class member is declared in Object from dart:core.
  bool isObjectMember(ClassBuilder objectClass);
  Uri get fileUri;
  int get charOffset;

  /// Returns `true` if this class member is an interface member.
  bool get isAbstract;

  /// Returns `true` if this member doesn't corresponds to a declaration in the
  /// source code.
  bool get isSynthesized;

  // If `true` this member is not part of the interface but only part of the
  // class members.
  //
  // This is `true` for instance for synthesized fields added for the late
  // lowering.
  bool get isInternalImplementation;

  /// Returns `true` if this member is composed from a list of class members
  /// accessible through [declarations].
  bool get hasDeclarations;

  /// If [hasDeclaration] is `true`, this returns the list of class members
  /// from which this class member is composed.
  ///
  /// This is used in [unfoldDeclarations] to retrieve all underlying member
  /// source declarations, and in [toSet] to retrieve all members used for
  /// this class member wrt. certain level of the hierarchy.
  /// TODO(johnniwinther): Can the use of [toSet] be replaced with a direct
  /// use of [declarations]?
  List<ClassMember> get declarations;

  /// The interface member corresponding to this member.
  ///
  /// If this member is declared on the source, the interface member is
  /// the member itself. For instance
  ///
  ///     abstract class Class {
  ///        void concreteMethod() {}
  ///        void abstractMethod();
  ///     }
  ///
  /// the interface members for `concreteMethod` and `abstractMethod` are the
  /// members themselves.
  ///
  /// If this member is a synthesized interface member, the
  /// interface member is the member itself. For instance
  ///
  ///     abstract class Interface1 {
  ///        void method() {}
  ///     }
  ///     abstract class Interface2 {
  ///        void method() {}
  ///     }
  ///     abstract class Class implements Interface1, Interface2 {}
  ///
  /// the interface member for `method` in `Class` is the synthesized interface
  /// member created for the implemented members `Interface1.method` and
  /// `Interface2.method`.
  ///
  /// If this member is a concrete member that implements an interface member,
  /// the interface member is the implemented interface member. For instance
  ///
  ///     class Super {
  ///        void method() {}
  ///     }
  ///     class Interface {
  ///        void method() {}
  ///     }
  ///     class Class extends Super implements Interface {}
  ///
  /// the interface member for `Super.method` implementing `method` in `Class`
  /// is the synthesized interface member created for the implemented members
  /// `Super.method` and `Interface.method`.
  ClassMember get interfaceMember;

  void inferType(ClassHierarchyBuilder hierarchy);
  void registerOverrideDependency(Set<ClassMember> overriddenMembers);

  /// Returns `true` if this has the same underlying declaration as [other].
  ///
  /// This is used for avoiding unnecessary checks and can this trivially
  /// return `false`.
  bool isSameDeclaration(ClassMember other);
}

bool hasSameSignature(FunctionNode a, FunctionNode b) {
  List<TypeParameter> aTypeParameters = a.typeParameters;
  List<TypeParameter> bTypeParameters = b.typeParameters;
  int typeParameterCount = aTypeParameters.length;
  if (typeParameterCount != bTypeParameters.length) return false;
  Substitution? substitution;
  if (typeParameterCount != 0) {
    List<DartType> types = new List<DartType>.generate(
        typeParameterCount,
        (int i) => new TypeParameterType.forAlphaRenaming(
            bTypeParameters[i], aTypeParameters[i]),
        growable: false);
    substitution = Substitution.fromPairs(bTypeParameters, types);
    for (int i = 0; i < typeParameterCount; i++) {
      DartType aBound = aTypeParameters[i].bound;
      DartType bBound = substitution.substituteType(bTypeParameters[i].bound);
      if (aBound != bBound) return false;
    }
  }

  if (a.requiredParameterCount != b.requiredParameterCount) return false;
  List<VariableDeclaration> aPositionalParameters = a.positionalParameters;
  List<VariableDeclaration> bPositionalParameters = b.positionalParameters;
  if (aPositionalParameters.length != bPositionalParameters.length) {
    return false;
  }
  for (int i = 0; i < aPositionalParameters.length; i++) {
    VariableDeclaration aParameter = aPositionalParameters[i];
    VariableDeclaration bParameter = bPositionalParameters[i];
    if (aParameter.isCovariant != bParameter.isCovariant) return false;
    DartType aType = aParameter.type;
    DartType bType = bParameter.type;
    if (substitution != null) {
      bType = substitution.substituteType(bType);
    }
    if (aType != bType) return false;
  }

  List<VariableDeclaration> aNamedParameters = a.namedParameters;
  List<VariableDeclaration> bNamedParameters = b.namedParameters;
  if (aNamedParameters.length != bNamedParameters.length) return false;
  for (int i = 0; i < aNamedParameters.length; i++) {
    VariableDeclaration aParameter = aNamedParameters[i];
    VariableDeclaration bParameter = bNamedParameters[i];
    if (aParameter.isCovariant != bParameter.isCovariant) return false;
    if (aParameter.name != bParameter.name) return false;
    DartType aType = aParameter.type;
    DartType bType = bParameter.type;
    if (substitution != null) {
      bType = substitution.substituteType(bType);
    }
    if (aType != bType) return false;
  }

  DartType aReturnType = a.returnType;
  DartType bReturnType = b.returnType;
  if (substitution != null) {
    bReturnType = substitution.substituteType(bReturnType);
  }

  return aReturnType == bReturnType;
}

class ClassHierarchyBuilder implements ClassHierarchyBase {
  final Map<Class, ClassHierarchyNode> nodes = <Class, ClassHierarchyNode>{};

  final Map<ClassBuilder, Map<Class, Substitution>> substitutions =
      <ClassBuilder, Map<Class, Substitution>>{};

  final ClassBuilder objectClassBuilder;

  final Loader loader;

  final Class objectClass;

  final Class futureClass;

  final Class functionClass;

  final List<DelayedTypeComputation> _delayedTypeComputations =
      <DelayedTypeComputation>[];

  final List<DelayedCheck> _delayedChecks = <DelayedCheck>[];

  final List<ClassMember> _delayedMemberComputations = <ClassMember>[];

  final CoreTypes coreTypes;

  late Types types;

  ClassHierarchyBuilder(this.objectClassBuilder, this.loader, this.coreTypes)
      : objectClass = objectClassBuilder.cls,
        futureClass = coreTypes.futureClass,
        functionClass = coreTypes.functionClass {
    types = new Types(this);
  }

  void clear() {
    nodes.clear();
    substitutions.clear();
    _delayedChecks.clear();
    _delayedTypeComputations.clear();
    _delayedMemberComputations.clear();
  }

  void registerDelayedTypeComputation(DelayedTypeComputation computation) {
    _delayedTypeComputations.add(computation);
  }

  void registerOverrideCheck(SourceClassBuilder classBuilder,
      ClassMember declaredMember, Set<ClassMember> overriddenMembers) {
    _delayedChecks.add(new DelayedOverrideCheck(
        classBuilder, declaredMember, overriddenMembers));
  }

  void registerGetterSetterCheck(
      SourceClassBuilder classBuilder, ClassMember getter, ClassMember setter) {
    _delayedChecks
        .add(new DelayedGetterSetterCheck(classBuilder, getter, setter));
  }

  void registerMemberComputation(ClassMember member) {
    _delayedMemberComputations.add(member);
  }

  List<DelayedTypeComputation> takeDelayedTypeComputations() {
    List<DelayedTypeComputation> list = _delayedTypeComputations.toList();
    _delayedTypeComputations.clear();
    return list;
  }

  List<DelayedCheck> takeDelayedChecks() {
    List<DelayedCheck> list = _delayedChecks.toList();
    _delayedChecks.clear();
    return list;
  }

  List<ClassMember> takeDelayedMemberComputations() {
    List<ClassMember> list = _delayedMemberComputations.toList();
    _delayedMemberComputations.clear();
    return list;
  }

  void inferFieldType(SourceFieldBuilder declaredMember,
      Iterable<ClassMember> overriddenMembers) {
    ClassHierarchyNodeBuilder.inferFieldType(
        this,
        declaredMember.classBuilder as SourceClassBuilder,
        declaredMember,
        overriddenMembers);
  }

  void inferGetterType(SourceProcedureBuilder declaredMember,
      Iterable<ClassMember> overriddenMembers) {
    ClassHierarchyNodeBuilder.inferGetterType(
        this,
        declaredMember.classBuilder as SourceClassBuilder,
        declaredMember,
        overriddenMembers);
  }

  void inferSetterType(SourceProcedureBuilder declaredMember,
      Iterable<ClassMember> overriddenMembers) {
    ClassHierarchyNodeBuilder.inferSetterType(
        this,
        declaredMember.classBuilder as SourceClassBuilder,
        declaredMember,
        overriddenMembers);
  }

  void inferMethodType(SourceProcedureBuilder declaredMember,
      Iterable<ClassMember> overriddenMembers) {
    ClassHierarchyNodeBuilder.inferMethodType(
        this,
        declaredMember.classBuilder as SourceClassBuilder,
        declaredMember,
        overriddenMembers);
  }

  ClassHierarchyNode getNodeFromClassBuilder(ClassBuilder classBuilder) {
    return nodes[classBuilder.cls] ??= new ClassHierarchyNodeBuilder(
            this, classBuilder, substitutions[classBuilder] ??= {})
        .build();
  }

  ClassHierarchyNode? getNodeFromTypeBuilder(TypeBuilder type) {
    ClassBuilder? cls = getClass(type);
    return cls == null ? null : getNodeFromClassBuilder(cls);
  }

  ClassHierarchyNode getNodeFromClass(Class cls) {
    return nodes[cls] ??
        getNodeFromClassBuilder(loader.computeClassBuilderFromTargetClass(cls));
  }

  Supertype? asSupertypeOf(InterfaceType subtype, Class supertype) {
    if (subtype.classNode == supertype) {
      return new Supertype(supertype, subtype.typeArguments);
    }
    ClassHierarchyNode clsNode = getNodeFromClass(subtype.classNode);
    ClassHierarchyNode supertypeNode = getNodeFromClass(supertype);
    List<Supertype> superclasses = clsNode.superclasses;
    int depth = supertypeNode.depth;
    if (depth < superclasses.length) {
      Supertype superclass = superclasses[depth];
      if (superclass.classNode == supertype) {
        return Substitution.fromInterfaceType(subtype)
            .substituteSupertype(superclass);
      }
    }
    List<Supertype> superinterfaces = clsNode.interfaces;
    for (int i = 0; i < superinterfaces.length; i++) {
      Supertype superinterface = superinterfaces[i];
      if (superinterface.classNode == supertype) {
        return Substitution.fromInterfaceType(subtype)
            .substituteSupertype(superinterface);
      }
    }
    return null;
  }

  InterfaceType getTypeAsInstanceOf(
      InterfaceType type, Class superclass, Library clientLibrary) {
    if (type.classNode == superclass) return type;
    return asSupertypeOf(type, superclass)!
        .asInterfaceType
        .withDeclaredNullability(type.nullability);
  }

  List<DartType>? getTypeArgumentsAsInstanceOf(
      InterfaceType type, Class superclass) {
    if (type.classNode == superclass) return type.typeArguments;
    return asSupertypeOf(type, superclass)?.typeArguments;
  }

  @override
  InterfaceType getLegacyLeastUpperBound(
      InterfaceType type1, InterfaceType type2, Library clientLibrary) {
    if (type1 == type2) return type1;

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

    ClassHierarchyNode node1 = getNodeFromClass(type1.classNode);
    ClassHierarchyNode node2 = getNodeFromClass(type2.classNode);
    Set<ClassHierarchyNode> nodes1 = node1.computeAllSuperNodes(this).toSet();
    List<ClassHierarchyNode> nodes2 = node2.computeAllSuperNodes(this);
    List<ClassHierarchyNode> common = <ClassHierarchyNode>[];

    for (int i = 0; i < nodes2.length; i++) {
      ClassHierarchyNode node = nodes2[i];
      // ignore: unnecessary_null_comparison
      if (node == null) continue;
      if (node.classBuilder.cls.isAnonymousMixin) {
        // Never find unnamed mixin application in least upper bound.
        continue;
      }
      if (nodes1.contains(node)) {
        DartType candidate1 =
            getTypeAsInstanceOf(type1, node.classBuilder.cls, clientLibrary);
        DartType candidate2 =
            getTypeAsInstanceOf(type2, node.classBuilder.cls, clientLibrary);
        if (candidate1 == candidate2) {
          common.add(node);
        }
      }
    }

    if (common.length == 1) {
      return coreTypes.objectRawType(
          uniteNullabilities(type1.nullability, type2.nullability));
    }
    common.sort(ClassHierarchyNode.compareMaxInheritancePath);

    for (int i = 0; i < common.length - 1; i++) {
      ClassHierarchyNode node = common[i];
      if (node.maxInheritancePath != common[i + 1].maxInheritancePath) {
        return getTypeAsInstanceOf(type1, node.classBuilder.cls, clientLibrary)
            .withDeclaredNullability(
                uniteNullabilities(type1.nullability, type2.nullability));
      } else {
        do {
          i++;
        } while (node.maxInheritancePath == common[i + 1].maxInheritancePath);
      }
    }
    return coreTypes.objectRawType(
        uniteNullabilities(type1.nullability, type2.nullability));
  }

  Member? getInterfaceMember(Class cls, Name name, {bool setter: false}) {
    return getNodeFromClass(cls)
        .getInterfaceMember(name, setter)
        ?.getMember(this);
  }

  ClassMember? getInterfaceClassMember(Class cls, Name name,
      {bool setter: false}) {
    return getNodeFromClass(cls).getInterfaceMember(name, setter);
  }

  static ClassHierarchyBuilder build(ClassBuilder objectClass,
      List<ClassBuilder> classes, SourceLoader loader, CoreTypes coreTypes) {
    ClassHierarchyBuilder hierarchy =
        new ClassHierarchyBuilder(objectClass, loader, coreTypes);
    for (int i = 0; i < classes.length; i++) {
      ClassBuilder classBuilder = classes[i];
      if (!classBuilder.isPatch) {
        hierarchy.nodes[classBuilder.cls] = new ClassHierarchyNodeBuilder(
                hierarchy,
                classBuilder,
                hierarchy.substitutions[classBuilder] ??= {})
            .build();
      } else {
        // TODO(ahe): Merge the injected members of patch into the hierarchy
        // node of `cls.origin`.
      }
    }
    return hierarchy;
  }

  void computeTypes() {
    List<DelayedTypeComputation> typeComputations =
        takeDelayedTypeComputations();
    for (int i = 0; i < typeComputations.length; i++) {
      typeComputations[i].compute(this);
    }
  }
}

class ClassHierarchyNodeBuilder {
  final ClassHierarchyBuilder hierarchy;

  final ClassBuilder classBuilder;

  bool hasNoSuchMethod = false;

  final Map<Class, Substitution> substitutions;

  ClassHierarchyNodeBuilder(
      this.hierarchy, this.classBuilder, this.substitutions);

  ClassBuilder get objectClass => hierarchy.objectClassBuilder;

  bool get shouldModifyKernel =>
      classBuilder.library.loader == hierarchy.loader;

  ClassMember? checkInheritanceConflict(ClassMember a, ClassMember b) {
    if (a.isStatic || a.isProperty != b.isProperty) {
      reportInheritanceConflict(a, b);
      return a;
    }
    return null;
  }

  static void inferMethodType(
      ClassHierarchyBuilder hierarchy,
      SourceClassBuilder classBuilder,
      SourceProcedureBuilder declaredMember,
      Iterable<ClassMember> overriddenMembers) {
    assert(!declaredMember.isGetter && !declaredMember.isSetter);
    if (declaredMember.classBuilder == classBuilder &&
        (declaredMember.returnType == null ||
            declaredMember.formals != null &&
                declaredMember.formals!
                    .any((parameter) => parameter.type == null))) {
      Procedure declaredProcedure = declaredMember.member as Procedure;
      FunctionNode declaredFunction = declaredProcedure.function;
      List<TypeParameter> declaredTypeParameters =
          declaredFunction.typeParameters;
      List<VariableDeclaration> declaredPositional =
          declaredFunction.positionalParameters;
      List<VariableDeclaration> declaredNamed =
          declaredFunction.namedParameters;
      declaredNamed = declaredNamed.toList()..sort(compareNamedParameters);

      DartType? inferredReturnType;
      Map<FormalParameterBuilder, DartType?> inferredParameterTypes = {};

      Set<ClassMember> overriddenMemberSet =
          toSet(classBuilder, overriddenMembers);
      CombinedClassMemberSignature combinedMemberSignature =
          new CombinedClassMemberSignature(
              hierarchy, classBuilder, overriddenMemberSet.toList(),
              forSetter: false);
      FunctionType? combinedMemberSignatureType = combinedMemberSignature
              .getCombinedSignatureTypeInContext(declaredTypeParameters)
          as FunctionType?;

      bool cantInferReturnType = false;
      List<FormalParameterBuilder>? cantInferParameterTypes;

      if (declaredMember.returnType == null) {
        if (combinedMemberSignatureType == null) {
          inferredReturnType = const InvalidType();
          cantInferReturnType = true;
        } else {
          inferredReturnType = combinedMemberSignatureType.returnType;
        }
      }
      if (declaredMember.formals != null) {
        for (int i = 0; i < declaredPositional.length; i++) {
          FormalParameterBuilder declaredParameter = declaredMember.formals![i];
          if (declaredParameter.type != null) {
            continue;
          }

          DartType? inferredParameterType;
          if (combinedMemberSignatureType == null) {
            inferredParameterType = const InvalidType();
            cantInferParameterTypes ??= [];
            cantInferParameterTypes.add(declaredParameter);
          } else if (i <
              combinedMemberSignatureType.positionalParameters.length) {
            inferredParameterType =
                combinedMemberSignatureType.positionalParameters[i];
          }
          inferredParameterTypes[declaredParameter] = inferredParameterType;
        }

        Map<String, DartType>? namedParameterTypes;
        for (int i = declaredPositional.length;
            i < declaredMember.formals!.length;
            i++) {
          FormalParameterBuilder declaredParameter = declaredMember.formals![i];
          if (declaredParameter.type != null) {
            continue;
          }

          DartType? inferredParameterType;
          if (combinedMemberSignatureType == null) {
            inferredParameterType = const InvalidType();
            cantInferParameterTypes ??= [];
            cantInferParameterTypes.add(declaredParameter);
          } else {
            if (namedParameterTypes == null) {
              namedParameterTypes = {};
              for (NamedType namedType
                  in combinedMemberSignatureType.namedParameters) {
                namedParameterTypes[namedType.name] = namedType.type;
              }
            }
            inferredParameterType = namedParameterTypes[declaredParameter.name];
          }
          inferredParameterTypes[declaredParameter] = inferredParameterType;
        }
      }

      if ((cantInferReturnType && cantInferParameterTypes != null) ||
          (cantInferParameterTypes != null &&
              cantInferParameterTypes.length > 1)) {
        reportCantInferTypes(
            classBuilder, declaredMember, hierarchy, overriddenMembers);
      } else if (cantInferReturnType) {
        reportCantInferReturnType(
            classBuilder, declaredMember, hierarchy, overriddenMembers);
      } else if (cantInferParameterTypes != null) {
        reportCantInferParameterType(classBuilder,
            cantInferParameterTypes.single, hierarchy, overriddenMembers);
      }

      if (declaredMember.returnType == null) {
        inferredReturnType ??= const DynamicType();
        declaredFunction.returnType = inferredReturnType;
      }
      if (declaredMember.formals != null) {
        for (FormalParameterBuilder declaredParameter
            in declaredMember.formals!) {
          if (declaredParameter.type == null) {
            DartType inferredParameterType =
                inferredParameterTypes[declaredParameter] ??
                    const DynamicType();
            declaredParameter.variable!.type = inferredParameterType;
          }
        }
      }
    }
  }

  void inferMethodSignature(ClassHierarchyBuilder hierarchy,
      ClassMember declaredMember, Iterable<ClassMember> overriddenMembers) {
    assert(!declaredMember.isGetter && !declaredMember.isSetter);
    // Trigger computation of method type.
    Procedure declaredProcedure =
        declaredMember.getMember(hierarchy) as Procedure;
    for (ClassMember overriddenMember
        in toSet(declaredMember.classBuilder, overriddenMembers)) {
      Covariance covariance = overriddenMember.getCovariance(hierarchy);
      covariance.applyCovariance(declaredProcedure);
    }
  }

  void inferGetterSignature(ClassHierarchyBuilder hierarchy,
      ClassMember declaredMember, Iterable<ClassMember> overriddenMembers) {
    assert(declaredMember.isGetter);
    // Trigger computation of the getter type.
    declaredMember.getMember(hierarchy);
    // Otherwise nothing to do. Getters have no variance.
  }

  void inferSetterSignature(ClassHierarchyBuilder hierarchy,
      ClassMember declaredMember, Iterable<ClassMember> overriddenMembers) {
    assert(declaredMember.isSetter);
    // Trigger computation of the getter type.
    Procedure declaredSetter = declaredMember.getMember(hierarchy) as Procedure;
    for (ClassMember overriddenMember
        in toSet(declaredMember.classBuilder, overriddenMembers)) {
      Covariance covariance = overriddenMember.getCovariance(hierarchy);
      covariance.applyCovariance(declaredSetter);
    }
  }

  static void inferGetterType(
      ClassHierarchyBuilder hierarchy,
      SourceClassBuilder classBuilder,
      SourceProcedureBuilder declaredMember,
      Iterable<ClassMember> overriddenMembers) {
    assert(declaredMember.isGetter);
    if (declaredMember.classBuilder == classBuilder &&
        declaredMember.returnType == null) {
      DartType? inferredType;
      overriddenMembers = toSet(classBuilder, overriddenMembers);

      List<ClassMember> overriddenGetters = [];
      List<ClassMember> overriddenSetters = [];
      for (ClassMember overriddenMember in overriddenMembers) {
        if (overriddenMember.forSetter) {
          overriddenSetters.add(overriddenMember);
        } else {
          overriddenGetters.add(overriddenMember);
        }
      }

      void inferFrom(List<ClassMember> members, {required bool forSetter}) {
        // ignore: unnecessary_null_comparison
        assert(forSetter != null);
        CombinedClassMemberSignature combinedMemberSignature =
            new CombinedClassMemberSignature(hierarchy, classBuilder, members,
                forSetter: forSetter);
        DartType? combinedMemberSignatureType =
            combinedMemberSignature.combinedMemberSignatureType;
        if (combinedMemberSignatureType == null) {
          inferredType = const InvalidType();
          reportCantInferReturnType(
              classBuilder, declaredMember, hierarchy, members);
        } else {
          inferredType = combinedMemberSignatureType;
        }
      }

      if (overriddenGetters.isNotEmpty) {
        // 1) The return type of a getter, parameter type of a setter or type
        // of a field which overrides/implements only one or more getters is
        // inferred to be the return type of the combined member signature of
        // said getter in the direct superinterfaces.

        // 2) The return type of a getter which overrides/implements both a
        // setter and a getter is inferred to be the return type of the
        // combined member signature of said getter in the direct
        // superinterfaces.
        inferFrom(overriddenGetters, forSetter: false);
      } else {
        // The return type of a getter, parameter type of a setter or type of
        // a field which overrides/implements only one or more setters is
        // inferred to be the parameter type of the combined member signature
        // of said setter in the direct superinterfaces.
        inferFrom(overriddenSetters, forSetter: true);
      }

      declaredMember.procedure.function.returnType =
          inferredType ?? const DynamicType();
    }
  }

  static void inferSetterType(
      ClassHierarchyBuilder hierarchy,
      SourceClassBuilder classBuilder,
      SourceProcedureBuilder declaredMember,
      Iterable<ClassMember> overriddenMembers) {
    assert(declaredMember.isSetter);
    FormalParameterBuilder parameter = declaredMember.formals!.first;
    if (declaredMember.classBuilder == classBuilder && parameter.type == null) {
      DartType? inferredType;

      overriddenMembers = toSet(classBuilder, overriddenMembers);

      List<ClassMember> overriddenGetters = [];
      List<ClassMember> overriddenSetters = [];
      for (ClassMember overriddenMember in overriddenMembers) {
        if (overriddenMember.forSetter) {
          overriddenSetters.add(overriddenMember);
        } else {
          overriddenGetters.add(overriddenMember);
        }
      }

      void inferFrom(List<ClassMember> members, {required bool forSetter}) {
        // ignore: unnecessary_null_comparison
        assert(forSetter != null);
        CombinedClassMemberSignature combinedMemberSignature =
            new CombinedClassMemberSignature(hierarchy, classBuilder, members,
                forSetter: forSetter);
        DartType? combinedMemberSignatureType =
            combinedMemberSignature.combinedMemberSignatureType;
        if (combinedMemberSignatureType == null) {
          inferredType = const InvalidType();
          reportCantInferReturnType(
              classBuilder, declaredMember, hierarchy, members);
        } else {
          inferredType = combinedMemberSignatureType;
        }
      }

      if (overriddenSetters.isNotEmpty) {
        // 1) The return type of a getter, parameter type of a setter or type
        // of a field which overrides/implements only one or more setters is
        // inferred to be the parameter type of the combined member signature
        // of said setter in the direct superinterfaces.
        //
        // 2) The parameter type of a setter which overrides/implements both a
        // setter and a getter is inferred to be the parameter type of the
        // combined member signature of said setter in the direct
        // superinterfaces.
        inferFrom(overriddenSetters, forSetter: true);
      } else {
        // The return type of a getter, parameter type of a setter or type of
        // a field which overrides/implements only one or more getters is
        // inferred to be the return type of the combined member signature of
        // said getter in the direct superinterfaces.
        inferFrom(overriddenGetters, forSetter: false);
      }

      parameter.variable!.type = inferredType ?? const DynamicType();
    }
  }

  /// Merge the [inheritedType] with the currently [inferredType] using
  /// nnbd-top-merge or legacy-top-merge depending on whether [classBuilder] is
  /// defined in an opt-in or opt-out library. If the types could not be merged
  /// `null` is returned and an error should be reported by the caller.
  static DartType? mergeTypeInLibrary(
      ClassHierarchyBuilder hierarchy,
      ClassBuilder classBuilder,
      DartType? inferredType,
      DartType inheritedType) {
    if (classBuilder.library.isNonNullableByDefault) {
      if (inferredType == null) {
        return inheritedType;
      } else {
        return nnbdTopMerge(
            hierarchy.coreTypes,
            norm(hierarchy.coreTypes, inferredType),
            norm(hierarchy.coreTypes, inheritedType));
      }
    } else {
      inheritedType = legacyErasure(inheritedType);
      if (inferredType == null) {
        return inheritedType;
      } else {
        if (inferredType is DynamicType &&
            inheritedType == hierarchy.coreTypes.objectLegacyRawType) {
          return inferredType;
        } else if (inheritedType is DynamicType &&
            inferredType == hierarchy.coreTypes.objectLegacyRawType) {
          return inheritedType;
        }
        if (inferredType != inheritedType) {
          return null;
        }
        return inferredType;
      }
    }
  }

  /// Infers the field type of [fieldBuilder] based on [overriddenMembers].
  static void inferFieldType(
      ClassHierarchyBuilder hierarchy,
      SourceClassBuilder classBuilder,
      SourceFieldBuilder fieldBuilder,
      Iterable<ClassMember> overriddenMembers) {
    if (fieldBuilder.classBuilder == classBuilder &&
        fieldBuilder.type == null) {
      DartType? inferredType;

      overriddenMembers = toSet(classBuilder, overriddenMembers);
      List<ClassMember> overriddenGetters = [];
      List<ClassMember> overriddenSetters = [];
      for (ClassMember overriddenMember in overriddenMembers) {
        if (overriddenMember.forSetter) {
          overriddenSetters.add(overriddenMember);
        } else {
          overriddenGetters.add(overriddenMember);
        }
      }

      DartType? inferFrom(List<ClassMember> members,
          {required bool forSetter}) {
        // ignore: unnecessary_null_comparison
        assert(forSetter != null);
        CombinedClassMemberSignature combinedMemberSignature =
            new CombinedClassMemberSignature(hierarchy, classBuilder, members,
                forSetter: forSetter);
        return combinedMemberSignature.combinedMemberSignatureType;
      }

      DartType? combinedMemberSignatureType;
      if (fieldBuilder.isAssignable &&
          overriddenGetters.isNotEmpty &&
          overriddenSetters.isNotEmpty) {
        // The type of a non-final field which overrides/implements both a
        // setter and a getter is inferred to be the parameter type of the
        // combined member signature of said setter in the direct
        // superinterfaces, if this type is the same as the return type of the
        // combined member signature of said getter in the direct
        // superinterfaces. If the types are not the same then inference fails
        // with an error.
        DartType? getterType = inferFrom(overriddenGetters, forSetter: false);
        DartType? setterType = inferFrom(overriddenSetters, forSetter: true);
        if (getterType == setterType) {
          combinedMemberSignatureType = getterType;
        }
      } else if (overriddenGetters.isNotEmpty) {
        // 1) The return type of a getter, parameter type of a setter or type
        // of a field which overrides/implements only one or more getters is
        // inferred to be the return type of the combined member signature of
        // said getter in the direct superinterfaces.
        //
        // 2) The type of a final field which overrides/implements both a
        // setter and a getter is inferred to be the return type of the
        // combined member signature of said getter in the direct
        // superinterfaces.
        combinedMemberSignatureType =
            inferFrom(overriddenGetters, forSetter: false);
      } else {
        // The return type of a getter, parameter type of a setter or type of
        // a field which overrides/implements only one or more setters is
        // inferred to be the parameter type of the combined member signature
        // of said setter in the direct superinterfaces.
        combinedMemberSignatureType =
            inferFrom(overriddenSetters, forSetter: true);
      }

      if (combinedMemberSignatureType == null) {
        inferredType = const InvalidType();
        reportCantInferFieldType(classBuilder, fieldBuilder, overriddenMembers);
      } else {
        inferredType = combinedMemberSignatureType;
      }

      fieldBuilder.fieldType = inferredType;
    }
  }

  /// Infers the field signature of [declaredMember] based on
  /// [overriddenMembers].
  void inferFieldSignature(ClassHierarchyBuilder hierarchy,
      ClassMember declaredMember, Iterable<ClassMember> overriddenMembers) {
    Field declaredField = declaredMember.getMember(hierarchy) as Field;
    for (ClassMember overriddenMember
        in toSet(declaredMember.classBuilder, overriddenMembers)) {
      Covariance covariance = overriddenMember.getCovariance(hierarchy);
      covariance.applyCovariance(declaredField);
    }
  }

  void reportInheritanceConflict(ClassMember a, ClassMember b) {
    String name = a.fullNameForErrors;
    if (a.classBuilder != b.classBuilder) {
      if (a.classBuilder == classBuilder) {
        classBuilder.addProblem(
            messageDeclaredMemberConflictsWithInheritedMember,
            a.charOffset,
            name.length,
            context: <LocatedMessage>[
              messageDeclaredMemberConflictsWithInheritedMemberCause
                  .withLocation(b.fileUri, b.charOffset, name.length)
            ]);
      } else if (b.classBuilder == classBuilder) {
        classBuilder.addProblem(
            messageDeclaredMemberConflictsWithInheritedMember,
            b.charOffset,
            name.length,
            context: <LocatedMessage>[
              messageDeclaredMemberConflictsWithInheritedMemberCause
                  .withLocation(a.fileUri, a.charOffset, name.length)
            ]);
      } else {
        classBuilder.addProblem(messageInheritedMembersConflict,
            classBuilder.charOffset, classBuilder.fullNameForErrors.length,
            context: _inheritedConflictContext(a, b));
      }
    } else if (a.isStatic != b.isStatic) {
      ClassMember staticMember;
      ClassMember instanceMember;
      if (a.isStatic) {
        staticMember = a;
        instanceMember = b;
      } else {
        staticMember = b;
        instanceMember = a;
      }
      classBuilder.library.addProblem(messageStaticAndInstanceConflict,
          staticMember.charOffset, name.length, staticMember.fileUri,
          context: <LocatedMessage>[
            messageStaticAndInstanceConflictCause.withLocation(
                instanceMember.fileUri, instanceMember.charOffset, name.length)
          ]);
    } else {
      // This message can be reported twice (when merging localMembers with
      // classSetters, or localSetters with classMembers). By ensuring that
      // we always report the one with higher charOffset as the duplicate,
      // the message duplication logic ensures that we only report this
      // problem once.
      ClassMember existing;
      ClassMember duplicate;
      assert(a.fileUri == b.fileUri);
      if (a.charOffset < b.charOffset) {
        existing = a;
        duplicate = b;
      } else {
        existing = b;
        duplicate = a;
      }
      classBuilder.library.addProblem(
          templateDuplicatedDeclaration.withArguments(name),
          duplicate.charOffset,
          name.length,
          duplicate.fileUri,
          context: <LocatedMessage>[
            templateDuplicatedDeclarationCause.withArguments(name).withLocation(
                existing.fileUri, existing.charOffset, name.length)
          ]);
    }
  }

  ClassHierarchyNode build() {
    assert(!classBuilder.isPatch);
    ClassHierarchyNode? supernode;
    if (objectClass != classBuilder.origin) {
      supernode =
          hierarchy.getNodeFromTypeBuilder(classBuilder.supertypeBuilder!);
      if (supernode == null) {
        supernode = hierarchy.getNodeFromClassBuilder(objectClass);
      }
      // ignore: unnecessary_null_comparison
      assert(supernode != null);
    }

    /// Set to `true` if the class needs interfaces, that is, if it has any
    /// members where the interface member is different from its corresponding
    /// class members.
    ///
    /// This is an optimization to avoid unnecessary computation of interface
    /// members.
    bool hasInterfaces = false;

    Map<Name, Tuple> memberMap = {};

    Scope scope = classBuilder.scope;

    for (Builder builder in scope.localMembers) {
      MemberBuilder memberBuilder = builder as MemberBuilder;
      for (ClassMember classMember in memberBuilder.localMembers) {
        if (classMember.isAbstract) {
          hasInterfaces = true;
        }
        Tuple? tuple = memberMap[classMember.name];
        if (tuple == null) {
          memberMap[classMember.name] = new Tuple.declareMember(classMember);
        } else {
          tuple.declaredMember = classMember;
        }
      }
      for (ClassMember classMember in memberBuilder.localSetters) {
        if (classMember.isAbstract) {
          hasInterfaces = true;
        }
        Tuple? tuple = memberMap[classMember.name];
        if (tuple == null) {
          memberMap[classMember.name] = new Tuple.declareSetter(classMember);
        } else {
          tuple.declaredSetter = classMember;
        }
      }
    }

    for (MemberBuilder memberBuilder in scope.localSetters) {
      for (ClassMember classMember in memberBuilder.localMembers) {
        if (classMember.isAbstract) {
          hasInterfaces = true;
        }
        Tuple? tuple = memberMap[classMember.name];
        if (tuple == null) {
          memberMap[classMember.name] = new Tuple.declareMember(classMember);
        } else {
          tuple.declaredMember = classMember;
        }
      }
      for (ClassMember classMember in memberBuilder.localSetters) {
        if (classMember.isAbstract) {
          hasInterfaces = true;
        }
        Tuple? tuple = memberMap[classMember.name];
        if (tuple == null) {
          memberMap[classMember.name] = new Tuple.declareSetter(classMember);
        } else {
          tuple.declaredSetter = classMember;
        }
      }
    }

    if (classBuilder.isMixinApplication) {
      TypeBuilder mixedInTypeBuilder = classBuilder.mixedInTypeBuilder!;
      TypeDeclarationBuilder mixin = mixedInTypeBuilder.declaration!;
      inferMixinApplication();
      while (mixin.isNamedMixinApplication) {
        ClassBuilder named = mixin as ClassBuilder;
        mixedInTypeBuilder = named.mixedInTypeBuilder!;
        mixin = mixedInTypeBuilder.declaration!;
      }
      if (mixin is TypeAliasBuilder) {
        TypeAliasBuilder aliasBuilder = mixin;
        NamedTypeBuilder namedBuilder = mixedInTypeBuilder as NamedTypeBuilder;
        mixin = aliasBuilder.unaliasDeclaration(namedBuilder.arguments,
            isUsedAsClass: true,
            usedAsClassCharOffset: namedBuilder.charOffset,
            usedAsClassFileUri: namedBuilder.fileUri)!;
      }
      if (mixin is ClassBuilder) {
        scope = mixin.scope.computeMixinScope();

        for (Builder builder in scope.localMembers) {
          MemberBuilder memberBuilder = builder as MemberBuilder;
          for (ClassMember classMember in memberBuilder.localMembers) {
            if (classMember.isAbstract) {
              hasInterfaces = true;
            }
            Tuple? tuple = memberMap[classMember.name];
            if (tuple == null) {
              memberMap[classMember.name] = new Tuple.mixInMember(classMember);
            } else {
              tuple.mixedInMember = classMember;
            }
          }
          for (ClassMember classMember in memberBuilder.localSetters) {
            if (classMember.isAbstract) {
              hasInterfaces = true;
            }
            Tuple? tuple = memberMap[classMember.name];
            if (tuple == null) {
              memberMap[classMember.name] = new Tuple.mixInSetter(classMember);
            } else {
              tuple.mixedInSetter = classMember;
            }
          }
        }

        for (MemberBuilder memberBuilder in scope.localSetters) {
          for (ClassMember classMember in memberBuilder.localMembers) {
            if (classMember.isAbstract) {
              hasInterfaces = true;
            }
            Tuple? tuple = memberMap[classMember.name];
            if (tuple == null) {
              memberMap[classMember.name] = new Tuple.mixInMember(classMember);
            } else {
              tuple.mixedInMember = classMember;
            }
          }
          for (ClassMember classMember in memberBuilder.localSetters) {
            if (classMember.isAbstract) {
              hasInterfaces = true;
            }
            Tuple? tuple = memberMap[classMember.name];
            if (tuple == null) {
              memberMap[classMember.name] = new Tuple.mixInSetter(classMember);
            } else {
              tuple.mixedInSetter = classMember;
            }
          }
        }
      }
    }

    List<Supertype> superclasses;

    List<Supertype> interfaces;

    int maxInheritancePath;

    void extend(Map<Name, ClassMember>? superClassMembers) {
      if (superClassMembers == null) return;
      for (MapEntry<Name, ClassMember> entry in superClassMembers.entries) {
        Name name = entry.key;
        ClassMember superClassMember = entry.value;
        Tuple? tuple = memberMap[name];
        if (tuple != null) {
          if (superClassMember.forSetter) {
            tuple.extendedSetter = superClassMember;
          } else {
            tuple.extendedMember = superClassMember;
          }
        } else {
          if (superClassMember.forSetter) {
            memberMap[name] = new Tuple.extendSetter(superClassMember);
          } else {
            memberMap[name] = new Tuple.extendMember(superClassMember);
          }
        }
      }
    }

    void implement(Map<Name, ClassMember>? superInterfaceMembers) {
      if (superInterfaceMembers == null) return;
      for (MapEntry<Name, ClassMember> entry in superInterfaceMembers.entries) {
        Name name = entry.key;
        ClassMember superInterfaceMember = entry.value;
        Tuple? tuple = memberMap[name];
        if (tuple != null) {
          if (superInterfaceMember.forSetter) {
            tuple.addImplementedSetter(superInterfaceMember);
          } else {
            tuple.addImplementedMember(superInterfaceMember);
          }
        } else {
          if (superInterfaceMember.forSetter) {
            memberMap[superInterfaceMember.name] =
                new Tuple.implementSetter(superInterfaceMember);
          } else {
            memberMap[superInterfaceMember.name] =
                new Tuple.implementMember(superInterfaceMember);
          }
        }
      }
    }

    if (supernode == null) {
      // This should be Object.
      superclasses = new List<Supertype>.filled(0, dummySupertype);
      interfaces = new List<Supertype>.filled(0, dummySupertype);
      maxInheritancePath = 0;
    } else {
      maxInheritancePath = supernode.maxInheritancePath + 1;

      superclasses = new List<Supertype>.filled(
          supernode.superclasses.length + 1, dummySupertype);
      Supertype? supertype = classBuilder.supertypeBuilder!.buildSupertype(
          classBuilder.library, classBuilder.charOffset, classBuilder.fileUri);
      if (supertype == null) {
        // If the superclass is not an interface type we use Object instead.
        // A similar normalization is performed on [supernode] above.
        supertype =
            new Supertype(hierarchy.coreTypes.objectClass, const <DartType>[]);
      }
      superclasses.setRange(0, superclasses.length - 1,
          substSupertypes(supertype, supernode.superclasses));
      superclasses[superclasses.length - 1] = supertype;
      if (!classBuilder.library.isNonNullableByDefault &&
          supernode.classBuilder.library.isNonNullableByDefault) {
        for (int i = 0; i < superclasses.length; i++) {
          superclasses[i] = legacyErasureSupertype(superclasses[i]);
        }
      }

      List<TypeBuilder>? directInterfaceBuilders =
          ignoreFunction(classBuilder.interfaceBuilders);
      if (classBuilder.isMixinApplication) {
        if (directInterfaceBuilders == null) {
          directInterfaceBuilders = <TypeBuilder>[
            classBuilder.mixedInTypeBuilder!
          ];
        } else {
          directInterfaceBuilders = <TypeBuilder>[
            classBuilder.mixedInTypeBuilder!
          ]..addAll(directInterfaceBuilders);
        }
      }

      List<Supertype> superclassInterfaces = supernode.interfaces;
      // ignore: unnecessary_null_comparison
      if (superclassInterfaces != null) {
        superclassInterfaces = substSupertypes(supertype, superclassInterfaces);
      }

      extend(supernode.classMemberMap);
      extend(supernode.classSetterMap);

      if (supernode.interfaceMemberMap != null ||
          supernode.interfaceSetterMap != null) {
        hasInterfaces = true;
      }

      if (hasInterfaces) {
        implement(supernode.interfaceMemberMap ?? supernode.classMemberMap);
        implement(supernode.interfaceSetterMap ?? supernode.classSetterMap);
      }

      if (directInterfaceBuilders != null) {
        for (int i = 0; i < directInterfaceBuilders.length; i++) {
          ClassHierarchyNode? interfaceNode =
              hierarchy.getNodeFromTypeBuilder(directInterfaceBuilders[i]);
          if (interfaceNode != null) {
            hasInterfaces = true;

            implement(interfaceNode.interfaceMemberMap ??
                interfaceNode.classMemberMap);
            implement(interfaceNode.interfaceSetterMap ??
                interfaceNode.classSetterMap);
          }
        }

        interfaces = <Supertype>[];
        // ignore: unnecessary_null_comparison
        if (superclassInterfaces != null) {
          for (int i = 0; i < superclassInterfaces.length; i++) {
            addInterface(interfaces, superclasses, superclassInterfaces[i]);
          }
        }

        for (int i = 0; i < directInterfaceBuilders.length; i++) {
          Supertype? directInterface = directInterfaceBuilders[i]
              .buildSupertype(classBuilder.library, classBuilder.charOffset,
                  classBuilder.fileUri);
          if (directInterface != null) {
            addInterface(interfaces, superclasses, directInterface);
            ClassHierarchyNode interfaceNode =
                hierarchy.getNodeFromClass(directInterface.classNode);
            // ignore: unnecessary_null_comparison
            if (interfaceNode != null) {
              if (maxInheritancePath < interfaceNode.maxInheritancePath + 1) {
                maxInheritancePath = interfaceNode.maxInheritancePath + 1;
              }

              List<Supertype> types =
                  substSupertypes(directInterface, interfaceNode.superclasses);
              for (int i = 0; i < types.length; i++) {
                addInterface(interfaces, superclasses, types[i]);
              }
              // ignore: unnecessary_null_comparison
              if (interfaceNode.interfaces != null) {
                List<Supertype> types =
                    substSupertypes(directInterface, interfaceNode.interfaces);
                for (int i = 0; i < types.length; i++) {
                  addInterface(interfaces, superclasses, types[i]);
                }
              }
            }
          }
        }
        // ignore: unnecessary_null_comparison
      } else if (superclassInterfaces != null &&
          !classBuilder.library.isNonNullableByDefault &&
          supernode.classBuilder.library.isNonNullableByDefault) {
        interfaces = <Supertype>[];
        for (int i = 0; i < superclassInterfaces.length; i++) {
          addInterface(interfaces, superclasses, superclassInterfaces[i]);
        }
      } else {
        interfaces = superclassInterfaces;
      }
    }

    for (Supertype superclass in superclasses) {
      recordSupertype(superclass);
    }
    // ignore: unnecessary_null_comparison
    if (interfaces != null) {
      for (Supertype superinterface in interfaces) {
        recordSupertype(superinterface);
      }
    }

    /// Members (excluding setters) declared in [cls] or its superclasses. This
    /// includes static methods of [cls], but not its superclasses.
    Map<Name, ClassMember> classMemberMap = {};

    /// Setters declared in [cls] or its superclasses. This includes static
    /// setters of [cls], but not its superclasses.
    Map<Name, ClassMember> classSetterMap = {};

    /// Members (excluding setters) inherited from interfaces. This contains no
    /// static members. If no interfaces are implemented by this class or its
    /// superclasses this is identical to [classMemberMap] and we do not store
    /// it in the [ClassHierarchyNode].
    Map<Name, ClassMember>? interfaceMemberMap = {};

    /// Setters inherited from interfaces. This contains no static setters. If
    /// no interfaces are implemented by this class or its superclasses this is
    /// identical to [classSetterMap] and we do not store it in the
    /// [ClassHierarchyNode].
    Map<Name, ClassMember>? interfaceSetterMap = {};

    /// Map for members declared in this class to the members that they
    /// override. This is used for checking valid overrides and to ensure that
    /// override inference correctly propagates inferred types through the
    /// class hierarchy.
    Map<ClassMember, Set<ClassMember>> declaredOverridesMap = {};

    /// In case this class is a mixin application, this maps members declared in
    /// the mixin to the members that they override. This is used for checking
    /// valid overrides but _not_ as for [declaredOverridesMap] for override
    /// inference.
    Map<ClassMember, Set<ClassMember>> mixinApplicationOverridesMap = {};

    /// In case this class is concrete, this maps concrete members that are
    /// inherited into this class to the members they should override to validly
    /// implement the interface of this class.
    Map<ClassMember, Set<ClassMember>> inheritedImplementsMap = {};

    /// In case this class is concrete, this holds the interface members
    /// without a corresponding class member. These are either reported as
    /// missing implementations or trigger insertion of noSuchMethod forwarders.
    List<ClassMember>? abstractMembers = [];

    ClassHierarchyNodeDataForTesting? dataForTesting;
    if (retainDataForTesting) {
      dataForTesting = new ClassHierarchyNodeDataForTesting(
          abstractMembers,
          declaredOverridesMap,
          mixinApplicationOverridesMap,
          inheritedImplementsMap);
    }

    /// Registers that the current class has an interface member without a
    /// corresponding class member.
    ///
    /// This is used to report missing implementation or, in the case the class
    /// has a user defined concrete noSuchMethod, to insert noSuchMethod
    /// forwarders. (Currently, insertion of forwarders is handled elsewhere.)
    ///
    /// For instance:
    ///
    ///    abstract class Interface {
    ///      method();
    ///    }
    ///    class Class1 implements Interface {
    ///      // Missing implementation for `Interface.method`.
    ///    }
    ///    class Class2 implements Interface {
    ///      noSuchMethod(_) {}
    ///      // A noSuchMethod forwarder is added for `Interface.method`.
    ///    }
    ///
    void registerAbstractMember(ClassMember abstractMember) {
      if (!abstractMember.isInternalImplementation) {
        /// If `isInternalImplementation` is `true`, the member is synthesized
        /// implementation that does not require implementation in other
        /// classes.
        ///
        /// This is for instance used for late lowering where
        ///
        ///    class Interface {
        ///      late int? field;
        ///    }
        ///    class Class implements Interface {
        ///      int? field;
        ///    }
        ///
        /// is encoded as
        ///
        ///    class Interface {
        ///      bool _#field#isSet = false;
        ///      int? _#field = null;
        ///      int? get field => _#field#isSet ? _#field : throw ...;
        ///      void set field(int? value) { ... }
        ///    }
        ///    class Class implements Interface {
        ///      int? field;
        ///    }
        ///
        /// and `Class` should not be required to implement
        /// `Interface._#field#isSet` and `Interface._#field`.
        abstractMembers.add(abstractMember);
      }
    }

    /// Registers that [inheritedMember] should be checked to validly override
    /// [overrides].
    ///
    /// This is needed in the case where a concrete member is inherited into
    /// a concrete subclass. For instance:
    ///
    ///    class Super {
    ///      void method() {}
    ///    }
    ///    abstract class Interface {
    ///      void method();
    ///    }
    ///    class Class extends Super implements Interface {}
    ///
    /// Here `Super.method` must be checked to be a valid implementation for
    /// `Interface.method` by being a valid override of it.
    void registerInheritedImplements(
        ClassMember inheritedMember, Set<ClassMember> overrides,
        {required ClassMember aliasForTesting}) {
      if (classBuilder is SourceClassBuilder) {
        assert(
            inheritedMember.classBuilder != classBuilder,
            "Only inherited members can implement by inheritance: "
            "${inheritedMember}");
        inheritedImplementsMap[inheritedMember] = overrides;
        // ignore: unnecessary_null_comparison
        if (dataForTesting != null && aliasForTesting != null) {
          dataForTesting.aliasMap[aliasForTesting] = inheritedMember;
        }
      }
    }

    /// Returns `true` if the current class is from an opt-out library and
    /// [classMember] is from an opt-in library.
    ///
    /// In this case a member signature needs to be inserted to show the
    /// legacy erased type of the interface member. For instance:
    ///
    ///    // Opt-in library:
    ///    class Super {
    ///      int? method(int i) {}
    ///    }
    ///    // Opt-out library:
    ///    class Class extends Super {
    ///      // A member signature is inserted:
    ///      // int* method(int* i);
    ///    }
    ///
    bool needsMemberSignatureFor(ClassMember classMember) {
      return !classBuilder.library.isNonNullableByDefault &&
          classMember.classBuilder.library.isNonNullableByDefault;
    }

    memberMap.forEach((Name name, Tuple tuple) {
      /// The computation starts by sanitizing the members. Conflicts between
      /// methods and properties (getters/setters) or between static and
      /// instance members are reported. Conflicting members and members
      /// overridden by duplicates are removed.
      ///
      /// For this [definingGetable] and [definingSetable] hold the first member
      /// of its kind found among declared, mixed in, extended and implemented
      /// members.
      ///
      /// Conflicts between [definingGetable] and [definingSetable] are reported
      /// afterwards.

      ClassMember? definingGetable;
      ClassMember? definingSetable;

      ClassMember? declaredGetable = tuple.declaredMember;
      if (declaredGetable != null) {
        /// class Class {
        ///   method() {}
        /// }
        definingGetable = declaredGetable;
      }
      ClassMember? declaredSetable = tuple.declaredSetter;
      if (declaredSetable != null) {
        /// class Class {
        ///   set setter(value) {}
        /// }
        definingSetable = declaredSetable;
      }

      ClassMember? mixedInGetable;
      ClassMember? tupleMixedInMember = tuple.mixedInMember;
      if (tupleMixedInMember != null &&
          !tupleMixedInMember.isStatic &&
          !tupleMixedInMember.isDuplicate &&
          !tupleMixedInMember.isSynthesized) {
        /// We treat
        ///
        ///   opt-in:
        ///   class Interface {
        ///     method3() {}
        ///   }
        ///   opt-out:
        ///   class Mixin implements Interface {
        ///     static method1() {}
        ///     method2() {}
        ///     method2() {}
        ///     /*member-signature*/ method3() {}
        ///   }
        ///   class Class with Mixin {}
        ///
        /// as
        ///
        ///   class Mixin {}
        ///   class Class with Mixin {}
        ///
        /// Note that skipped synthetic getable 'method3' is still included
        /// in the implemented getables, but its type will not define the type
        /// when mixed in. For instance
        ///
        ///   opt-in:
        ///   abstract class Interface {
        ///     num get getter;
        ///   }
        ///   opt-out:
        ///   abstract class Super {
        ///     int get getter;
        ///   }
        ///   abstract class Mixin implements Interface {
        ///     /*member-signature*/ num get getter;
        ///   }
        ///   abstract class Class extends Super with Mixin {}
        ///
        /// Here the type of `Class.getter` should not be defined from the
        /// synthetic member signature `Mixin.getter` but as a combined member
        /// signature of `Super.getter` and `Mixin.getter`, resulting in type
        /// `int` instead of `num`.
        if (definingGetable == null) {
          /// class Mixin {
          ///   method() {}
          /// }
          /// class Class with Mixin {}
          definingGetable = mixedInGetable = tupleMixedInMember;
        } else if (!definingGetable.isDuplicate) {
          // This case is currently unreachable from source code since classes
          // cannot both declare and mix in members. From dill, this can occur
          // but should not conflicting members.
          //
          // The case is handled for consistency.
          if (definingGetable.isStatic ||
              definingGetable.isProperty != tupleMixedInMember.isProperty) {
            reportInheritanceConflict(definingGetable, tupleMixedInMember);
          } else {
            mixedInGetable = tupleMixedInMember;
          }
        }
      }
      ClassMember? mixedInSetable;
      ClassMember? tupleMixedInSetter = tuple.mixedInSetter;
      if (tupleMixedInSetter != null &&
          !tupleMixedInSetter.isStatic &&
          !tupleMixedInSetter.isDuplicate &&
          !tupleMixedInSetter.isSynthesized) {
        /// We treat
        ///
        ///   class Mixin {
        ///     static set setter1(value) {}
        ///     set setter2(value) {}
        ///     set setter2(value) {}
        ///     /*member-signature*/ setter3() {}
        ///   }
        ///   class Class with Mixin {}
        ///
        /// as
        ///
        ///   class Mixin {}
        ///   class Class with Mixin {}
        ///
        /// Note that skipped synthetic setable 'setter3' is still included
        /// in the implemented setables, but its type will not define the type
        /// when mixed in. For instance
        ///
        ///   opt-in:
        ///   abstract class Interface {
        ///     void set setter(int value);
        ///   }
        ///   opt-out:
        ///   abstract class Super {
        ///     void set setter(num value);
        ///   }
        ///   abstract class Mixin implements Interface {
        ///     /*member-signature*/ num get getter;
        ///   }
        ///   abstract class Class extends Super with Mixin {}
        ///
        /// Here the type of `Class.setter` should not be defined from the
        /// synthetic member signature `Mixin.setter` but as a combined member
        /// signature of `Super.setter` and `Mixin.setter`, resulting in type
        /// `num` instead of `int`.
        if (definingSetable == null) {
          /// class Mixin {
          ///   set setter(value) {}
          /// }
          /// class Class with Mixin {}
          definingSetable = mixedInSetable = tupleMixedInSetter;
        } else if (!definingSetable.isDuplicate) {
          if (definingSetable.isStatic ||
              definingSetable.isProperty != tupleMixedInSetter.isProperty) {
            reportInheritanceConflict(definingSetable, tupleMixedInSetter);
          } else {
            mixedInSetable = tupleMixedInSetter;
          }
        }
      }

      ClassMember? extendedGetable;
      ClassMember? tupleExtendedMember = tuple.extendedMember;
      if (tupleExtendedMember != null &&
          !tupleExtendedMember.isStatic &&
          !tupleExtendedMember.isDuplicate) {
        /// We treat
        ///
        ///   class Super {
        ///     static method1() {}
        ///     method2() {}
        ///     method2() {}
        ///   }
        ///   class Class extends Super {}
        ///
        /// as
        ///
        ///   class Super {}
        ///   class Class extends Super {}
        ///
        if (definingGetable == null) {
          /// class Super {
          ///   method() {}
          /// }
          /// class Class extends Super {}
          definingGetable = extendedGetable = tupleExtendedMember;
        } else if (!definingGetable.isDuplicate) {
          if (definingGetable.isStatic ||
              definingGetable.isProperty != tupleExtendedMember.isProperty) {
            ///   class Super {
            ///     method() {}
            ///   }
            ///   class Class extends Super {
            ///     static method() {}
            ///   }
            ///
            /// or
            ///
            ///   class Super {
            ///     method() {}
            ///   }
            ///   class Class extends Super {
            ///     get getter => 0;
            ///   }
            reportInheritanceConflict(definingGetable, tupleExtendedMember);
          } else {
            extendedGetable = tupleExtendedMember;
          }
        }
      }
      ClassMember? extendedSetable;
      ClassMember? tupleExtendedSetter = tuple.extendedSetter;
      if (tupleExtendedSetter != null &&
          !tupleExtendedSetter.isStatic &&
          !tupleExtendedSetter.isDuplicate) {
        /// We treat
        ///
        ///   class Super {
        ///     static set setter1(value) {}
        ///     set setter2(value) {}
        ///     set setter2(value) {}
        ///   }
        ///   class Class extends Super {}
        ///
        /// as
        ///
        ///   class Super {}
        ///   class Class extends Super {}
        ///
        if (definingSetable == null) {
          /// class Super {
          ///   set setter(value) {}
          /// }
          /// class Class extends Super {}
          definingSetable = extendedSetable = tupleExtendedSetter;
        } else if (!definingSetable.isDuplicate) {
          if (definingSetable.isStatic ||
              definingSetable.isProperty != tupleExtendedSetter.isProperty) {
            reportInheritanceConflict(definingSetable, tupleExtendedSetter);
          } else {
            extendedSetable = tupleExtendedSetter;
          }
        }
      }

      // TODO(johnniwinther): Remove extended and mixed in members/setters
      // from implemented members/setters. Mixin applications always implement
      // the mixin class leading to unnecessary interface members.
      List<ClassMember>? implementedGetables;
      List<ClassMember>? tupleImplementedMembers = tuple.implementedMembers;
      if (tupleImplementedMembers != null &&
          // Skip implemented members if we already have a duplicate.
          !(definingGetable != null && definingGetable.isDuplicate)) {
        for (int i = 0; i < tupleImplementedMembers.length; i++) {
          ClassMember? implementedGetable = tupleImplementedMembers[i];
          if (implementedGetable.isStatic || implementedGetable.isDuplicate) {
            /// We treat
            ///
            ///   class Interface {
            ///     static method1() {}
            ///     method2() {}
            ///     method2() {}
            ///   }
            ///   class Class implements Interface {}
            ///
            /// as
            ///
            ///   class Interface {}
            ///   class Class implements Interface {}
            ///
            implementedGetable = null;
          } else {
            if (definingGetable == null) {
              /// class Interface {
              ///   method() {}
              /// }
              /// class Class implements Interface {}
              definingGetable = implementedGetable;
            } else if (definingGetable.isStatic ||
                definingGetable.isProperty != implementedGetable.isProperty) {
              ///   class Interface {
              ///     method() {}
              ///   }
              ///   class Class implements Interface {
              ///     static method() {}
              ///   }
              ///
              /// or
              ///
              ///   class Interface {
              ///     method() {}
              ///   }
              ///   class Class implements Interface {
              ///     get getter => 0;
              ///   }
              reportInheritanceConflict(definingGetable, implementedGetable);
              implementedGetable = null;
            }
          }
          if (implementedGetable == null) {
            // On the first skipped member we add all previous.
            implementedGetables ??= tupleImplementedMembers.take(i).toList();
          } else if (implementedGetables != null) {
            // If already skipping members we add [implementedGetable]
            // explicitly.
            implementedGetables.add(implementedGetable);
          }
        }
        if (implementedGetables == null) {
          // No members were skipped so we use the full list.
          implementedGetables = tupleImplementedMembers;
        } else if (implementedGetables.isEmpty) {
          // No members were included.
          implementedGetables = null;
        }
      }

      List<ClassMember>? implementedSetables;
      List<ClassMember>? tupleImplementedSetters = tuple.implementedSetters;
      if (tupleImplementedSetters != null &&
          // Skip implemented setters if we already have a duplicate.
          !(definingSetable != null && definingSetable.isDuplicate)) {
        for (int i = 0; i < tupleImplementedSetters.length; i++) {
          ClassMember? implementedSetable = tupleImplementedSetters[i];
          if (implementedSetable.isStatic || implementedSetable.isDuplicate) {
            /// We treat
            ///
            ///   class Interface {
            ///     static set setter1(value) {}
            ///     set setter2(value) {}
            ///     set setter2(value) {}
            ///   }
            ///   class Class implements Interface {}
            ///
            /// as
            ///
            ///   class Interface {}
            ///   class Class implements Interface {}
            ///
            implementedSetable = null;
          } else {
            if (definingSetable == null) {
              /// class Interface {
              ///   set setter(value) {}
              /// }
              /// class Class implements Interface {}
              definingSetable = implementedSetable;
            } else if (definingSetable.isStatic ||
                definingSetable.isProperty != implementedSetable.isProperty) {
              /// class Interface {
              ///   set setter(value) {}
              /// }
              /// class Class implements Interface {
              ///   static set setter(value) {}
              /// }
              reportInheritanceConflict(definingSetable, implementedSetable);
              implementedSetable = null;
            }
          }
          if (implementedSetable == null) {
            // On the first skipped setter we add all previous.
            implementedSetables ??= tupleImplementedSetters.take(i).toList();
          } else if (implementedSetables != null) {
            // If already skipping setters we add [implementedSetable]
            // explicitly.
            implementedSetables.add(implementedSetable);
          }
        }
        if (implementedSetables == null) {
          // No setters were skipped so we use the full list.
          implementedSetables = tupleImplementedSetters;
        } else if (implementedSetables.isEmpty) {
          // No setters were included.
          implementedSetables = null;
        }
      }

      if (definingGetable != null && definingSetable != null) {
        if (definingGetable.isStatic != definingSetable.isStatic ||
            definingGetable.isProperty != definingSetable.isProperty) {
          reportInheritanceConflict(definingGetable, definingSetable);
          // TODO(johnniwinther): Should we remove [definingSetable]? If we
          // leave it in this conflict will also be reported in subclasses. If
          // we remove it, any write to the setable will be unresolved.
        }
      }

      // TODO(johnniwinther): Handle declared members together with mixed in
      // members. This should only occur from .dill, though.
      if (mixedInGetable != null) {
        declaredGetable = null;
      }
      if (mixedInSetable != null) {
        declaredSetable = null;
      }

      /// Set to `true` if declared members have been registered in
      /// [registerDeclaredOverride] or [registerMixedInOverride].
      bool hasDeclaredMembers = false;

      /// Declared methods, getters and setters registered in
      /// [registerDeclaredOverride].
      ClassMember? declaredMethod;
      List<ClassMember>? declaredProperties;

      /// Declared methods, getters and setters registered in
      /// [registerDeclaredOverride].
      ClassMember? mixedInMethod;
      List<ClassMember>? mixedInProperties;

      /// Registers that [declaredMember] overrides extended and implemented
      /// members.
      ///
      /// Getters and setters share overridden members so the registration
      /// of override relations is performed after the interface members have
      /// been computed.
      ///
      /// Declared members must be checked for valid override of the overridden
      /// members _and_ must register an override dependency with the overridden
      /// members so that override inference can propagate inferred types
      /// correctly. For instance:
      ///
      ///    class Super {
      ///      int get property => 42;
      ///    }
      ///    class Class extends Super {
      ///      void set property(value) {}
      ///    }
      ///
      /// Here the parameter type of the setter `Class.property` must be
      /// inferred from the type of the getter `Super.property`.
      void registerDeclaredOverride(ClassMember declaredMember,
          {ClassMember? aliasForTesting}) {
        if (classBuilder is SourceClassBuilder && !declaredMember.isStatic) {
          assert(
              declaredMember.isSourceDeclaration &&
                  declaredMember.classBuilder == classBuilder,
              "Only declared members can override: ${declaredMember}");
          hasDeclaredMembers = true;
          if (declaredMember.isProperty) {
            declaredProperties ??= [];
            declaredProperties!.add(declaredMember);
          } else {
            assert(
                declaredMethod == null,
                "Multiple methods unexpectedly declared: "
                "${declaredMethod} and ${declaredMember}.");
            declaredMethod = declaredMember;
          }
          if (dataForTesting != null && aliasForTesting != null) {
            dataForTesting.aliasMap[aliasForTesting] = declaredMember;
          }
        }
      }

      /// Registers that [mixedMember] overrides extended and implemented
      /// members through application.
      ///
      /// Getters and setters share overridden members so the registration
      /// of override relations in performed after the interface members have
      /// been computed.
      ///
      /// Declared mixed in members must be checked for valid override of the
      /// overridden members but _not_ register an override dependency with the
      /// overridden members. This is in contrast to declared members. For
      /// instance:
      ///
      ///    class Super {
      ///      int get property => 42;
      ///    }
      ///    class Mixin {
      ///      void set property(value) {}
      ///    }
      ///    class Class = Super with Mixin;
      ///
      /// Here the parameter type of the setter `Mixin.property` must _not_ be
      /// inferred from the type of the getter `Super.property`, but should
      /// instead default to `dynamic`.
      void registerMixedInOverride(ClassMember mixedInMember,
          {ClassMember? aliasForTesting}) {
        assert(mixedInMember.classBuilder != classBuilder,
            "Only mixin members can override by application: ${mixedInMember}");
        if (classBuilder is SourceClassBuilder) {
          hasDeclaredMembers = true;
          if (mixedInMember.isProperty) {
            mixedInProperties ??= [];
            mixedInProperties!.add(mixedInMember);
          } else {
            assert(
                mixedInMethod == null,
                "Multiple methods unexpectedly declared in mixin: "
                "${mixedInMethod} and ${mixedInMember}.");
            mixedInMethod = mixedInMember;
          }
          if (dataForTesting != null && aliasForTesting != null) {
            dataForTesting.aliasMap[aliasForTesting] = mixedInMember;
          }
        }
      }

      /// Computes the class and interface members for a method, getter, or
      /// setter in the current [tuple].
      ///
      /// [definingMember] is the member which defines whether the computation
      /// is for a method, a getter or a setter.
      /// [declaredMember] is the member declared in the current class, if any.
      /// [mixedInMember] is the member declared in a mixin that is mixed into
      /// the current current class, if any.
      /// [extendedMember] is the member inherited from the super class.
      /// [implementedMembers] are the members inherited from the super
      /// interfaces, if none this is `null`.
      ///
      /// The computed class and interface members are added to [classMemberMap]
      /// and [interfaceMemberMap], respectively.
      ClassMember? computeMembers(
          {required ClassMember definingMember,
          required ClassMember? declaredMember,
          required ClassMember? mixedInMember,
          required ClassMember? extendedMember,
          required List<ClassMember>? implementedMembers,
          required Map<Name, ClassMember> classMemberMap,
          required Map<Name, ClassMember>? interfaceMemberMap}) {
        ClassMember? classMember;
        ClassMember? interfaceMember;

        if (mixedInMember != null) {
          if (mixedInMember.isAbstract) {
            ///    class Mixin {
            ///      method();
            ///    }
            ///    class Class = Object with Mixin;

            /// Interface members from the extended, mixed in, and implemented
            /// members define the combined member signature.
            Set<ClassMember> interfaceMembers = {};

            if (extendedMember != null) {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Mixin {
              ///      method();
              ///    }
              ///    class Class = Super with Mixin;
              interfaceMembers.add(extendedMember.interfaceMember);
            }

            interfaceMembers.add(mixedInMember);

            if (implementedMembers != null) {
              ///    class Interface {
              ///      method() {}
              ///    }
              ///    class Mixin {
              ///      method();
              ///    }
              ///    class Class = Object with Mixin implements Interface;
              interfaceMembers.addAll(implementedMembers);
            }

            /// We always create a synthesized interface member, even in the
            /// case of [interfaceMembers] being a singleton, to insert the
            /// abstract mixin stub.
            interfaceMember = new SynthesizedInterfaceMember(
                classBuilder, name, interfaceMembers.toList(),
                superClassMember: extendedMember,
                // [definingMember] and [mixedInMember] are always the same
                // here. Use the latter here and the former below to show the
                // the member is canonical _because_ its the mixed in member and
                // it defines the isProperty/forSetter properties _because_ it
                // is the defining member.
                canonicalMember: mixedInMember,
                mixedInMember: mixedInMember,
                isProperty: definingMember.isProperty,
                forSetter: definingMember.forSetter,
                shouldModifyKernel: shouldModifyKernel);
            hierarchy.registerMemberComputation(interfaceMember);

            if (extendedMember != null) {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Mixin {
              ///      method();
              ///    }
              ///    class Class = Super with Mixin;
              ///
              /// The concrete extended member is the class member but might
              /// be overwritten by a concrete forwarding stub:
              ///
              ///    class Super {
              ///      method(int i) {}
              ///    }
              ///    class Interface {
              ///      method(covariant int i) {}
              ///    }
              ///    class Mixin {
              ///      method(int i);
              ///    }
              ///    // A concrete forwarding stub
              ///    //   method(covariant int i) => super.method(i);
              ///    // will be inserted.
              ///    class Class = Super with Mixin implements Interface;
              ///
              classMember = new InheritedClassMemberImplementsInterface(
                  classBuilder, name,
                  inheritedClassMember: extendedMember,
                  implementedInterfaceMember: interfaceMember,
                  forSetter: definingMember.forSetter,
                  isProperty: definingMember.isProperty);
              hierarchy.registerMemberComputation(classMember);
              if (!classBuilder.isAbstract) {
                registerInheritedImplements(extendedMember, {interfaceMember},
                    aliasForTesting: classMember);
              }
            } else if (!classBuilder.isAbstract) {
              ///    class Mixin {
              ///      method(); // Missing implementation.
              ///    }
              ///    class Class = Object with Mixin;
              registerAbstractMember(interfaceMember);
            }

            assert(!mixedInMember.isSynthesized);
            if (!mixedInMember.isSynthesized) {
              /// Members declared in the mixin must override extended and
              /// implemented members.
              ///
              /// When loading from .dill the mixed in member might be
              /// synthesized, for instance a member signature or forwarding
              /// stub, and this should not be checked to override the extended
              /// and implemented members:
              ///
              ///    // Opt-out library, from source:
              ///    class Mixin {}
              ///    // Opt-out library, from .dill:
              ///    class Mixin {
              ///      ...
              ///      String* toString(); // member signature
              ///    }
              ///    // Opt-out library, from source:
              ///    class Class = Object with Mixin;
              ///    // Mixin.toString should not be checked to override
              ///    // Object.toString.
              ///
              registerMixedInOverride(mixedInMember,
                  aliasForTesting: interfaceMember);
            }
          } else {
            assert(!mixedInMember.isAbstract);

            ///    class Mixin {
            ///      method() {}
            ///    }
            ///    class Class = Object with Mixin;
            ///

            /// Interface members from the extended, mixed in, and implemented
            /// members define the combined member signature.
            Set<ClassMember> interfaceMembers = {};

            if (extendedMember != null) {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Mixin {
              ///      method() {}
              ///    }
              ///    class Class = Super with Mixin;
              interfaceMembers.add(extendedMember.interfaceMember);
            }

            interfaceMembers.add(mixedInMember);

            if (implementedMembers != null) {
              ///    class Interface {
              ///      method() {}
              ///    }
              ///    class Mixin {
              ///      method() {}
              ///    }
              ///    class Class = Object with Mixin implements Interface;
              interfaceMembers.addAll(implementedMembers);
            }

            /// We always create a synthesized interface member, even in the
            /// case of [interfaceMembers] being a singleton, to insert the
            /// concrete mixin stub.
            interfaceMember = new SynthesizedInterfaceMember(
                classBuilder, name, interfaceMembers.toList(),
                superClassMember: mixedInMember,
                // [definingMember] and [mixedInMember] are always the same
                // here. Use the latter here and the former below to show the
                // the member is canonical _because_ its the mixed in member and
                // it defines the isProperty/forSetter properties _because_ it
                // is the defining member.
                canonicalMember: mixedInMember,
                mixedInMember: mixedInMember,
                isProperty: definingMember.isProperty,
                forSetter: definingMember.forSetter,
                shouldModifyKernel: shouldModifyKernel);
            hierarchy.registerMemberComputation(interfaceMember);

            /// The concrete mixed in member is the class member but will
            /// be overwritten by a concrete mixin stub:
            ///
            ///    class Mixin {
            ///       method() {}
            ///    }
            ///    // A concrete mixin stub
            ///    //   method() => super.method();
            ///    // will be inserted.
            ///    class Class = Object with Mixin;
            ///
            classMember = new InheritedClassMemberImplementsInterface(
                classBuilder, name,
                inheritedClassMember: mixedInMember,
                implementedInterfaceMember: interfaceMember,
                forSetter: definingMember.forSetter,
                isProperty: definingMember.isProperty);
            hierarchy.registerMemberComputation(classMember);

            if (!classBuilder.isAbstract) {
              ///    class Interface {
              ///      method() {}
              ///    }
              ///    class Mixin {
              ///      method() {}
              ///    }
              ///    class Class = Object with Mixin;
              ///
              /// [mixinMember] must implemented interface member.
              registerInheritedImplements(mixedInMember, {interfaceMember},
                  aliasForTesting: classMember);
            }
            assert(!mixedInMember.isSynthesized);
            if (!mixedInMember.isSynthesized) {
              /// Members declared in the mixin must override extended and
              /// implemented members.
              ///
              /// When loading from .dill the mixed in member might be
              /// synthesized, for instance a member signature or forwarding
              /// stub, and this should not be checked to override the extended
              /// and implemented members.
              ///
              /// These synthesized mixed in members should always be abstract
              /// and therefore not be handled here, but we handled them here
              /// for consistency.
              registerMixedInOverride(mixedInMember);
            }
          }
        } else if (declaredMember != null) {
          if (declaredMember.isAbstract) {
            ///    class Class {
            ///      method();
            ///    }
            interfaceMember = declaredMember;

            /// Interface members from the declared, extended, and implemented
            /// members define the combined member signature.
            Set<ClassMember> interfaceMembers = {};

            if (extendedMember != null) {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Class extends Super {
              ///      method();
              ///    }
              interfaceMembers.add(extendedMember);
            }

            interfaceMembers.add(declaredMember);

            if (implementedMembers != null) {
              ///    class Interface {
              ///      method() {}
              ///    }
              ///    class Class implements Interface {
              ///      method();
              ///    }
              interfaceMembers.addAll(implementedMembers);
            }

            /// If only one member defines the interface member there is no
            /// need for a synthesized interface member, since its result will
            /// simply be that one member.
            if (interfaceMembers.length > 1) {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Interface {
              ///      method() {}
              ///    }
              ///    class Class extends Super implements Interface {
              ///      method();
              ///    }
              interfaceMember = new SynthesizedInterfaceMember(
                  classBuilder, name, interfaceMembers.toList(),
                  superClassMember: extendedMember,
                  // [definingMember] and [declaredMember] are always the same
                  // here. Use the latter here and the former below to show the
                  // the member is canonical _because_ its the declared member
                  // and it defines the isProperty/forSetter properties
                  // _because_ it is the defining member.
                  canonicalMember: declaredMember,
                  isProperty: definingMember.isProperty,
                  forSetter: definingMember.forSetter,
                  shouldModifyKernel: shouldModifyKernel);
              hierarchy.registerMemberComputation(interfaceMember);
            }

            if (extendedMember != null) {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Class extends Super {
              ///      method();
              ///    }
              ///
              /// The concrete extended member is the class member but might
              /// be overwritten by a concrete forwarding stub:
              ///
              ///    class Super {
              ///      method(int i) {}
              ///    }
              ///    class Interface {
              ///      method(covariant int i) {}
              ///    }
              ///    class Class extends Super implements Interface {
              ///      // This will be turned into the concrete forwarding stub
              ///      //    method(covariant int i) => super.method(i);
              ///      method(int i);
              ///    }
              ///
              classMember = new InheritedClassMemberImplementsInterface(
                  classBuilder, name,
                  inheritedClassMember: extendedMember,
                  implementedInterfaceMember: interfaceMember,
                  forSetter: definingMember.forSetter,
                  isProperty: definingMember.isProperty);
              hierarchy.registerMemberComputation(classMember);

              if (!classBuilder.isAbstract) {
                ///    class Super {
                ///      method() {}
                ///    }
                ///    class Class extends Super {
                ///      method();
                ///    }
                ///
                /// [extendedMember] must implemented interface member.
                registerInheritedImplements(extendedMember, {interfaceMember},
                    aliasForTesting: classMember);
              }
            } else if (!classBuilder.isAbstract) {
              ///    class Class {
              ///      method(); // Missing implementation.
              ///    }
              registerAbstractMember(declaredMember);
            }

            /// The declared member must override extended and implemented
            /// members.
            registerDeclaredOverride(declaredMember,
                aliasForTesting: interfaceMember);
          } else {
            assert(!declaredMember.isAbstract);

            ///    class Class {
            ///      method() {}
            ///    }
            classMember = declaredMember;

            /// The declared member must override extended and implemented
            /// members.
            registerDeclaredOverride(declaredMember);
          }
        } else if (extendedMember != null) {
          ///    class Super {
          ///      method() {}
          ///    }
          ///    class Class extends Super {}
          assert(!extendedMember.isAbstract,
              "Abstract extended member: ${extendedMember}");

          classMember = extendedMember;

          if (implementedMembers != null) {
            ///    class Super {
            ///      method() {}
            ///    }
            ///    class Interface {
            ///      method() {}
            ///    }
            ///    class Class extends Super implements Interface {}
            ClassMember extendedInterfaceMember =
                extendedMember.interfaceMember;

            /// Interface members from the extended and implemented
            /// members define the combined member signature.
            Set<ClassMember> interfaceMembers = {extendedInterfaceMember};

            // TODO(johnniwinther): The extended member might be included in
            // a synthesized implemented member. For instance:
            //
            //    class Super {
            //      void method() {}
            //    }
            //    class Interface {
            //      void method() {}
            //    }
            //    abstract class Class extends Super implements Interface {
            //      // Synthesized interface member of
            //      //   {Super.method, Interface.method}
            //    }
            //    class Sub extends Class {
            //      // Super.method implements Class.method =
            //      //   {Super.method, Interface.method}
            //      // Synthesized interface member of
            //      //   {Super.method, Class.method}
            //    }
            //
            // Maybe we should recognized this.
            interfaceMembers.addAll(implementedMembers);

            /// Normally, if only one member defines the interface member there
            /// is no need for a synthesized interface member, since its result
            /// will simply be that one member, but if the extended member is
            /// from an opt-in library and the current class is from an opt-out
            /// library we need to create a member signature:
            ///
            ///    // Opt-in:
            ///    class Super {
            ///      int? method() => null;
            ///    }
            ///    class Interface implements Super {}
            ///    // Opt-out:
            ///    class Class extends Super implements Interface {
            ///      // Member signature added:
            ///      int* method();
            ///    }
            ///
            if (interfaceMembers.length == 1 &&
                !needsMemberSignatureFor(extendedInterfaceMember)) {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Interface implements Super {}
              ///    class Class extends Super implements Interface {}
              interfaceMember = interfaceMembers.first;
            } else {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Interface {
              ///      method() {}
              ///    }
              ///    class Class extends Super implements Interface {}
              interfaceMember = new SynthesizedInterfaceMember(
                  classBuilder, name, interfaceMembers.toList(),
                  superClassMember: extendedMember,
                  isProperty: definingMember.isProperty,
                  forSetter: definingMember.forSetter,
                  shouldModifyKernel: shouldModifyKernel);
              hierarchy.registerMemberComputation(interfaceMember);
            }
            if (interfaceMember == classMember) {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Interface implements Super {}
              ///    class Class extends Super implements Interface {}
              ///
              /// We keep track of whether a class needs interfaces, that is,
              /// whether is has any members that have an interface member
              /// different from its corresponding class member, so we set
              /// [interfaceMember] to `null` so show that the interface member
              /// is not needed.
              interfaceMember = null;
            } else {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Interface {
              ///      method() {}
              ///    }
              ///    class Class extends Super implements Interface {}
              ///
              /// The concrete extended member is the class member but might
              /// be overwritten by a concrete forwarding stub:
              ///
              ///    class Super {
              ///      method(int i) {}
              ///    }
              ///    class Interface {
              ///      method(covariant int i) {}
              ///    }
              ///    class Class extends Super implements Interface {
              ///      // A concrete forwarding stub will be created:
              ///      //    method(covariant int i) => super.method(i);
              ///    }
              ///
              classMember = new InheritedClassMemberImplementsInterface(
                  classBuilder, name,
                  inheritedClassMember: extendedMember,
                  implementedInterfaceMember: interfaceMember,
                  isProperty: definingMember.isProperty,
                  forSetter: definingMember.forSetter);
              hierarchy.registerMemberComputation(classMember);
              if (!classBuilder.isAbstract) {
                ///    class Super {
                ///      method() {}
                ///    }
                ///    class Interface {
                ///      method() {}
                ///    }
                ///    class Class extends Super implements Interface {}
                registerInheritedImplements(extendedMember, {interfaceMember},
                    aliasForTesting: classMember);
              }
            }
          } else if (needsMemberSignatureFor(extendedMember)) {
            ///    // Opt-in library:
            ///    class Super {
            ///      method() {}
            ///    }
            ///    // opt-out library:
            ///    class Class extends Super {}
            interfaceMember = new SynthesizedInterfaceMember(
                classBuilder, name, [extendedMember],
                superClassMember: extendedMember,
                isProperty: definingMember.isProperty,
                forSetter: definingMember.forSetter,
                shouldModifyKernel: shouldModifyKernel);
            hierarchy.registerMemberComputation(interfaceMember);

            /// The concrete extended member is the class member and should
            /// be able to be overwritten by a synthesized concrete member here,
            /// but we handle the case for consistency.
            classMember = new InheritedClassMemberImplementsInterface(
                classBuilder, name,
                inheritedClassMember: extendedMember,
                implementedInterfaceMember: interfaceMember,
                isProperty: definingMember.isProperty,
                forSetter: definingMember.forSetter);
            hierarchy.registerMemberComputation(classMember);
          }
        } else if (implementedMembers != null) {
          ///    class Interface {
          ///      method() {}
          ///    }
          ///    class Class implements Interface {}
          Set<ClassMember> interfaceMembers = implementedMembers.toSet();
          if (interfaceMembers.isNotEmpty) {
            /// Normally, if only one member defines the interface member there
            /// is no need for a synthesized interface member, since its result
            /// will simply be that one member, but if the implemented member is
            /// from an opt-in library and the current class is from an opt-out
            /// library we need to create a member signature:
            ///
            ///    // Opt-in:
            ///    class Interface {
            ///      int? method() => null;
            ///    }
            ///    // Opt-out:
            ///    class Class implements Interface {
            ///      // Member signature added:
            ///      int* method();
            ///    }
            ///
            if (interfaceMembers.length == 1 &&
                !needsMemberSignatureFor(interfaceMembers.first)) {
              ///    class Interface {
              ///      method() {}
              ///    }
              ///    class Class implements Interface {}
              interfaceMember = interfaceMembers.first;
            } else {
              ///    class Interface1 {
              ///      method() {}
              ///    }
              ///    class Interface2 {
              ///      method() {}
              ///    }
              ///    class Class implements Interface1, Interface2 {}
              interfaceMember = new SynthesizedInterfaceMember(
                  classBuilder, name, interfaceMembers.toList(),
                  isProperty: definingMember.isProperty,
                  forSetter: definingMember.forSetter,
                  shouldModifyKernel: shouldModifyKernel);
              hierarchy.registerMemberComputation(interfaceMember);
            }
            if (!classBuilder.isAbstract) {
              ///    class Interface {
              ///      method() {}
              ///    }
              ///    class Class implements Interface {}
              for (ClassMember abstractMember in interfaceMembers) {
                registerAbstractMember(abstractMember);
              }
            }
          }
        }

        if (interfaceMember != null) {
          // We have an explicit interface.
          hasInterfaces = true;
        }
        if (classMember != null) {
          if (name == noSuchMethodName &&
              !classMember.isObjectMember(objectClass)) {
            hasNoSuchMethod = true;
          }
          classMemberMap[name] = classMember;
          interfaceMember ??= classMember.interfaceMember;
        }
        if (interfaceMember != null) {
          interfaceMemberMap![name] = interfaceMember;
        }
        return interfaceMember;
      }

      ClassMember? interfaceGetable;
      if (definingGetable != null) {
        interfaceGetable = computeMembers(
            definingMember: definingGetable,
            declaredMember: declaredGetable,
            mixedInMember: mixedInGetable,
            extendedMember: extendedGetable,
            implementedMembers: implementedGetables,
            classMemberMap: classMemberMap,
            interfaceMemberMap: interfaceMemberMap);
      }
      ClassMember? interfaceSetable;
      if (definingSetable != null) {
        interfaceSetable = computeMembers(
            definingMember: definingSetable,
            declaredMember: declaredSetable,
            mixedInMember: mixedInSetable,
            extendedMember: extendedSetable,
            implementedMembers: implementedSetables,
            classMemberMap: classSetterMap,
            interfaceMemberMap: interfaceSetterMap);
      }
      if (classBuilder is SourceClassBuilder) {
        if (interfaceGetable != null &&
            interfaceSetable != null &&
            interfaceGetable.isProperty &&
            interfaceSetable.isProperty &&
            interfaceGetable.isStatic == interfaceSetable.isStatic &&
            !interfaceGetable.isSameDeclaration(interfaceSetable)) {
          /// We need to check that the getter type is a subtype of the setter
          /// type. For instance
          ///
          ///    class Super {
          ///       int get property1 => null;
          ///       num get property2 => null;
          ///    }
          ///    class Mixin {
          ///       void set property1(num value) {}
          ///       void set property2(int value) {}
          ///    }
          ///    class Class = Super with Mixin;
          ///
          /// Here `Super.property1` and `Mixin.property1` form a valid getter/
          /// setter pair in `Class` because the type of the getter
          /// `Super.property1` is a subtype of the setter `Mixin.property1`.
          ///
          /// In contrast the pair `Super.property2` and `Mixin.property2` is
          /// not a valid getter/setter in `Class` because the type of the getter
          /// `Super.property2` is _not_ a subtype of the setter
          /// `Mixin.property1`.
          hierarchy.registerGetterSetterCheck(
              classBuilder as SourceClassBuilder,
              interfaceGetable,
              interfaceSetable);
        }
      }
      if (hasDeclaredMembers) {
        Set<ClassMember> getableOverrides = {};
        Set<ClassMember> setableOverrides = {};
        if (extendedGetable != null) {
          ///    (abstract) class Super {
          ///      method() {}
          ///      int get property => 0;
          ///    }
          ///    (abstract) class Class extends Super {
          ///      method() {}
          ///      set property(int value) {}
          ///    }
          getableOverrides.add(extendedGetable.interfaceMember);
        }
        if (extendedSetable != null) {
          ///    (abstract) class Super {
          ///      set setter(int value) {}
          ///      set property(int value) {}
          ///    }
          ///    (abstract) class Class extends Super {
          ///      set setter(int value) {}
          ///      int get property => 0;
          ///    }
          setableOverrides.add(extendedSetable.interfaceMember);
        }
        if (implementedGetables != null) {
          ///    (abstract) class Interface {
          ///      method() {}
          ///      int get property => 0;
          ///    }
          ///    (abstract) class Class implements Interface {
          ///      method() {}
          ///      set property(int value) {}
          ///    }
          getableOverrides.addAll(implementedGetables);
        }
        if (implementedSetables != null) {
          ///    (abstract) class Interface {
          ///      set setter(int value) {}
          ///      set property(int value) {}
          ///    }
          ///    (abstract) class Class implements Interface {
          ///      set setter(int value) {}
          ///      int get property => 0;
          ///    }
          setableOverrides.addAll(implementedSetables);
        }
        if (getableOverrides.isNotEmpty || setableOverrides.isNotEmpty) {
          if (declaredMethod != null && getableOverrides.isNotEmpty) {
            ///    class Super {
            ///      method() {}
            ///    }
            ///    class Class extends Super {
            ///      method() {}
            ///    }
            declaredOverridesMap[declaredMethod!] = getableOverrides;
          }
          if (declaredProperties != null) {
            Set<ClassMember> overrides;
            if (declaredMethod != null) {
              ///    class Super {
              ///      set setter() {}
              ///    }
              ///    class Class extends Super {
              ///      method() {}
              ///    }
              overrides = setableOverrides;
            } else {
              ///    class Super {
              ///      get property => null
              ///      void set property(value) {}
              ///    }
              ///    class Class extends Super {
              ///      get property => null
              ///      void set property(value) {}
              ///    }
              overrides = {...getableOverrides, ...setableOverrides};
            }
            if (overrides.isNotEmpty) {
              for (ClassMember declaredMember in declaredProperties!) {
                declaredOverridesMap[declaredMember] = overrides;
              }
            }
          }
          if (mixedInMethod != null && getableOverrides.isNotEmpty) {
            ///    class Super {
            ///      method() {}
            ///    }
            ///    class Mixin {
            ///      method() {}
            ///    }
            ///    class Class = Super with Mixin;
            mixinApplicationOverridesMap[mixedInMethod!] = getableOverrides;
          }
          if (mixedInProperties != null) {
            Set<ClassMember> overrides;
            if (mixedInMethod != null) {
              ///    class Super {
              ///      set setter() {}
              ///    }
              ///    class Mixin {
              ///      method() {}
              ///    }
              ///    class Class = Super with Mixin;
              overrides = setableOverrides;
            } else {
              ///    class Super {
              ///      method() {}
              ///    }
              ///    class Mixin extends Super {
              ///      method() {}
              ///    }
              overrides = {...getableOverrides, ...setableOverrides};
            }
            if (overrides.isNotEmpty) {
              for (ClassMember mixedInMember in mixedInProperties!) {
                mixinApplicationOverridesMap[mixedInMember] = overrides;
              }
            }
          }
        }
      }
    });

    if (classBuilder is SourceClassBuilder) {
      // TODO(johnniwinther): Avoid duplicate override check computations
      //  between [declaredOverridesMap], [mixinApplicationOverridesMap] and
      //  [inheritedImplementsMap].

      // TODO(johnniwinther): Ensure that a class member is only checked to
      // validly override another member once. Currently it can happen multiple
      // times as an inherited implementation.

      declaredOverridesMap.forEach(
          (ClassMember classMember, Set<ClassMember> overriddenMembers) {
        /// A declared member can inherit its type from the overridden members.
        ///
        /// We register this with the class member itself so the it can force
        /// computation of type on the overridden members before determining its
        /// own type.
        ///
        /// Member types can be queried at arbitrary points during top level
        /// inference so we need to ensure that types are computed in dependency
        /// order.
        classMember.registerOverrideDependency(overriddenMembers);

        /// Not all member type are queried during top level inference so we
        /// register delayed computation to ensure that all types have been
        /// computed before override checks are performed.
        DelayedTypeComputation computation =
            new DelayedTypeComputation(this, classMember, overriddenMembers);
        hierarchy.registerDelayedTypeComputation(computation);

        /// Declared members must be checked to validly override the the
        /// overridden members.
        hierarchy.registerOverrideCheck(
            classBuilder as SourceClassBuilder, classMember, overriddenMembers);
      });

      mixinApplicationOverridesMap.forEach(
          (ClassMember classMember, Set<ClassMember> overriddenMembers) {
        /// Declared mixed in members must be checked to validly override the
        /// overridden members.
        hierarchy.registerOverrideCheck(
            classBuilder as SourceClassBuilder, classMember, overriddenMembers);
      });

      inheritedImplementsMap.forEach(
          (ClassMember classMember, Set<ClassMember> overriddenMembers) {
        /// Concrete members must be checked to validly override the overridden
        /// members in concrete classes.
        hierarchy.registerOverrideCheck(
            classBuilder as SourceClassBuilder, classMember, overriddenMembers);
      });
    }

    if (!hasInterfaces) {
      /// All interface members also class members to we don't need to store
      /// the interface members separately.
      assert(
          classMemberMap.length == interfaceMemberMap.length,
          "Class/interface member mismatch. Class members: "
          "$classMemberMap, interface members: $interfaceMemberMap.");
      assert(
          classSetterMap.length == interfaceSetterMap.length,
          "Class/interface setter mismatch. Class setters: "
          "$classSetterMap, interface setters: $interfaceSetterMap.");
      assert(
          classMemberMap.keys.every((Name name) =>
              identical(classMemberMap[name], interfaceMemberMap?[name])),
          "Class/interface member mismatch. Class members: "
          "$classMemberMap, interface members: $interfaceMemberMap.");
      assert(
          classSetterMap.keys.every((Name name) =>
              identical(classSetterMap[name], interfaceSetterMap?[name])),
          "Class/interface setter mismatch. Class setters: "
          "$classSetterMap, interface setters: $interfaceSetterMap.");
      interfaceMemberMap = null;
      interfaceSetterMap = null;
    }

    // ignore: unnecessary_null_comparison
    if (abstractMembers != null && !classBuilder.isAbstract) {
      if (!hasNoSuchMethod) {
        reportMissingMembers(abstractMembers);
      } else {
        installNsmHandlers();
      }
    }

    return new ClassHierarchyNode(
        classBuilder,
        classMemberMap,
        classSetterMap,
        interfaceMemberMap,
        interfaceSetterMap,
        superclasses,
        interfaces,
        maxInheritancePath,
        hasNoSuchMethod,
        dataForTesting);
  }

  Supertype recordSupertype(Supertype supertype) {
    debug?.log("In ${this.classBuilder.fullNameForErrors} "
        "recordSupertype(${supertype})");
    Class cls = supertype.classNode;
    List<TypeParameter> supertypeTypeParameters = cls.typeParameters;
    if (supertypeTypeParameters.isEmpty) {
      substitutions[cls] = Substitution.empty;
    } else {
      List<DartType> arguments = supertype.typeArguments;
      List<DartType> typeArguments =
          new List<DartType>.filled(arguments.length, dummyDartType);
      List<TypeParameter> typeParameters =
          new List<TypeParameter>.filled(arguments.length, dummyTypeParameter);
      for (int i = 0; i < arguments.length; i++) {
        typeParameters[i] = supertypeTypeParameters[i];
        typeArguments[i] = arguments[i];
      }
      substitutions[cls] =
          Substitution.fromPairs(typeParameters, typeArguments);
    }
    return supertype;
  }

  List<Supertype> substSupertypes(
      Supertype supertype, List<Supertype> supertypes) {
    List<TypeParameter> typeVariables = supertype.classNode.typeParameters;
    if (typeVariables.isEmpty) {
      debug?.log("In ${this.classBuilder.fullNameForErrors} "
          "$supertypes aren't substed");
      return supertypes;
    }
    Map<TypeParameter, DartType> map = <TypeParameter, DartType>{};
    List<DartType> arguments = supertype.typeArguments;
    for (int i = 0; i < typeVariables.length; i++) {
      map[typeVariables[i]] = arguments[i];
    }
    Substitution substitution = Substitution.fromMap(map);
    List<Supertype>? result;
    for (int i = 0; i < supertypes.length; i++) {
      Supertype supertype = supertypes[i];
      Supertype substituted = substitution.substituteSupertype(supertype);
      if (supertype != substituted) {
        debug?.log("In ${this.classBuilder.fullNameForErrors} $supertype"
            " -> $substituted");
        result ??= supertypes.toList();
        result[i] = substituted;
      } else {
        debug?.log("In ${this.classBuilder.fullNameForErrors} "
            "$supertype isn't substed");
      }
    }
    return result ?? supertypes;
  }

  void addInterface(List<Supertype> interfaces, List<Supertype> superclasses,
      Supertype type) {
    // ignore: unnecessary_null_comparison
    if (type == null) return null;
    if (!classBuilder.library.isNonNullableByDefault) {
      type = legacyErasureSupertype(type);
    }
    ClassHierarchyNode node = hierarchy.getNodeFromClass(type.classNode);
    // ignore: unnecessary_null_comparison
    if (node == null) return null;
    int depth = node.depth;
    int myDepth = superclasses.length;
    Supertype? superclass = depth < myDepth ? superclasses[depth] : null;
    if (superclass != null && superclass.classNode == type.classNode) {
      // This is a potential conflict.
      if (classBuilder.library.isNonNullableByDefault) {
        superclass = nnbdTopMergeSupertype(
            hierarchy.coreTypes,
            normSupertype(hierarchy.coreTypes, superclass),
            normSupertype(hierarchy.coreTypes, type));
        if (superclass == null) {
          // This is a conflict.
          // TODO(johnniwinther): Report errors here instead of through
          // the computation of the [ClassHierarchy].
          superclass = superclasses[depth];
        } else {
          superclasses[depth] = superclass;
        }
      }
      return;
    } else {
      for (int i = 0; i < interfaces.length; i++) {
        // This is a quadratic algorithm, but normally, the number of
        // interfaces is really small.
        Supertype? interface = interfaces[i];
        if (interface.classNode == type.classNode) {
          // This is a potential conflict.
          if (classBuilder.library.isNonNullableByDefault) {
            interface = nnbdTopMergeSupertype(
                hierarchy.coreTypes,
                normSupertype(hierarchy.coreTypes, interface),
                normSupertype(hierarchy.coreTypes, type));
            if (interface == null) {
              // This is a conflict.
              // TODO(johnniwinther): Report errors here instead of through
              // the computation of the [ClassHierarchy].
              interface = interfaces[i];
            } else {
              interfaces[i] = interface;
            }
          }
          return;
        }
      }
    }
    interfaces.add(type);
  }

  void reportMissingMembers(List<ClassMember> abstractMembers) {
    Map<String, LocatedMessage> contextMap = <String, LocatedMessage>{};
    for (ClassMember declaration in unfoldDeclarations(abstractMembers)) {
      if (isNameVisibleIn(declaration.name, classBuilder.library)) {
        String name = declaration.fullNameForErrors;
        String className = declaration.classBuilder.fullNameForErrors;
        String displayName =
            declaration.isSetter ? "$className.$name=" : "$className.$name";
        contextMap[displayName] = templateMissingImplementationCause
            .withArguments(displayName)
            .withLocation(
                declaration.fileUri, declaration.charOffset, name.length);
      }
    }
    if (contextMap.isEmpty) return;
    List<String> names = new List<String>.from(contextMap.keys)..sort();
    List<LocatedMessage> context = <LocatedMessage>[];
    for (int i = 0; i < names.length; i++) {
      context.add(contextMap[names[i]]!);
    }
    classBuilder.addProblem(
        templateMissingImplementationNotAbstract.withArguments(
            classBuilder.fullNameForErrors, names),
        classBuilder.charOffset,
        classBuilder.fullNameForErrors.length,
        context: context);
  }

  void installNsmHandlers() {
    // TODO(ahe): Implement this.
  }

  void inferMixinApplication() {
    Class cls = classBuilder.cls;
    Supertype? mixedInType = cls.mixedInType;
    if (mixedInType == null) return;
    List<DartType> typeArguments = mixedInType.typeArguments;
    if (typeArguments.isEmpty || typeArguments.first is! UnknownType) return;
    new BuilderMixinInferrer(
            classBuilder,
            hierarchy.coreTypes,
            new TypeBuilderConstraintGatherer(hierarchy,
                mixedInType.classNode.typeParameters, cls.enclosingLibrary))
        .infer(cls);
    List<TypeBuilder> inferredArguments = new List<TypeBuilder>.generate(
        typeArguments.length,
        (int i) => hierarchy.loader.computeTypeBuilder(typeArguments[i]),
        growable: false);
    NamedTypeBuilder mixedInTypeBuilder =
        classBuilder.mixedInTypeBuilder as NamedTypeBuilder;
    mixedInTypeBuilder.arguments = inferredArguments;
  }

  /// The class Function from dart:core is supposed to be ignored when used as
  /// an interface.
  List<TypeBuilder>? ignoreFunction(List<TypeBuilder>? interfaces) {
    if (interfaces == null) return null;
    for (int i = 0; i < interfaces!.length; i++) {
      ClassBuilder? classBuilder = getClass(interfaces[i]);
      if (classBuilder != null && classBuilder.cls == hierarchy.functionClass) {
        if (interfaces.length == 1) {
          return null;
        } else {
          interfaces = interfaces.toList();
          interfaces.removeAt(i);
          return ignoreFunction(interfaces);
        }
      }
    }
    return interfaces;
  }
}

class ClassHierarchyNode {
  /// The class corresponding to this hierarchy node.
  final ClassBuilder classBuilder;

  /// All the members of this class including [classMembers] of its
  /// superclasses. The members are sorted by [compareDeclarations].
  final Map<Name, ClassMember> classMemberMap;

  /// Similar to [classMembers] but for setters.
  final Map<Name, ClassMember> classSetterMap;

  /// All the interface members of this class including [interfaceMembers] of
  /// its supertypes. The members are sorted by [compareDeclarations].
  ///
  /// In addition to the members of [classMembers] this also contains members
  /// from interfaces.
  ///
  /// This may be null, in which case [classMembers] is the interface members.
  final Map<Name, ClassMember>? interfaceMemberMap;

  /// Similar to [interfaceMembers] but for setters.
  ///
  /// This may be null, in which case [classSetters] is the interface setters.
  final Map<Name, ClassMember>? interfaceSetterMap;

  /// All superclasses of [classBuilder] excluding itself. The classes are
  /// sorted by depth from the root (Object) in ascending order.
  final List<Supertype> superclasses;

  /// The list of all classes implemented by [classBuilder] and its supertypes
  /// excluding any classes from [superclasses].
  final List<Supertype> interfaces;

  /// The longest inheritance path from [classBuilder] to `Object`.
  final int maxInheritancePath;

  int get depth => superclasses.length;

  final bool hasNoSuchMethod;

  final ClassHierarchyNodeDataForTesting? dataForTesting;

  ClassHierarchyNode(
      this.classBuilder,
      this.classMemberMap,
      this.classSetterMap,
      this.interfaceMemberMap,
      this.interfaceSetterMap,
      this.superclasses,
      this.interfaces,
      this.maxInheritancePath,
      this.hasNoSuchMethod,
      this.dataForTesting);

  /// Returns a list of all supertypes of [classBuilder], including this node.
  List<ClassHierarchyNode> computeAllSuperNodes(
      ClassHierarchyBuilder hierarchy) {
    List<ClassHierarchyNode> result = [];
    for (int i = 0; i < superclasses.length; i++) {
      Supertype type = superclasses[i];
      result.add(hierarchy.getNodeFromClass(type.classNode));
    }
    for (int i = 0; i < interfaces.length; i++) {
      Supertype type = interfaces[i];
      result.add(hierarchy.getNodeFromClass(type.classNode));
    }
    result.add(this);
    return result;
  }

  String toString() {
    StringBuffer sb = new StringBuffer();
    sb
      ..write(classBuilder.fullNameForErrors)
      ..writeln(":");
    if (maxInheritancePath != this.depth) {
      sb
        ..write("  Longest path to Object: ")
        ..writeln(maxInheritancePath);
    }
    sb..writeln("  superclasses:");
    int depth = 0;
    for (Supertype superclass in superclasses) {
      sb.write("  " * (depth + 2));
      if (depth != 0) sb.write("-> ");
      sb.write(typeToText(superclass.asInterfaceType));
      sb.writeln();
      depth++;
    }
    // ignore: unnecessary_null_comparison
    if (interfaces != null) {
      sb.write("  interfaces:");
      bool first = true;
      for (Supertype i in interfaces) {
        if (!first) sb.write(",");
        sb.write(" ");
        sb.write(typeToText(i.asInterfaceType));
        first = false;
      }
      sb.writeln();
    }
    printMemberMap(classMemberMap, sb, "classMembers");
    printMemberMap(classSetterMap, sb, "classSetters");
    if (interfaceMemberMap != null) {
      printMemberMap(interfaceMemberMap!, sb, "interfaceMembers");
    }
    if (interfaceSetterMap != null) {
      printMemberMap(interfaceSetterMap!, sb, "interfaceSetters");
    }
    return "$sb";
  }

  void printMembers(
      List<ClassMember> members, StringBuffer sb, String heading) {
    sb.write("  ");
    sb.write(heading);
    sb.writeln(":");
    for (ClassMember member in members) {
      sb
        ..write("    ")
        ..write(member.classBuilder.fullNameForErrors)
        ..write(".")
        ..write(member.fullNameForErrors)
        ..writeln();
    }
  }

  void printMemberMap(
      Map<Name, ClassMember> memberMap, StringBuffer sb, String heading) {
    List<ClassMember> members = memberMap.values.toList();
    members.sort(compareDeclarations);
    printMembers(members, sb, heading);
  }

  ClassMember? getInterfaceMember(Name name, bool isSetter) {
    return isSetter
        ? (interfaceSetterMap ?? classSetterMap)[name]
        : (interfaceMemberMap ?? classMemberMap)[name];
  }

  ClassMember? findMember(Name name, List<ClassMember> declarations) {
    // TODO(ahe): Consider creating a map or scope. The obvious choice would be
    // to use scopes, but they don't handle private names correctly.

    // This is a copy of `ClassHierarchy.findMemberByName`.
    int low = 0, high = declarations.length - 1;
    while (low <= high) {
      int mid = low + ((high - low) >> 1);
      ClassMember pivot = declarations[mid];
      int comparison = ClassHierarchy.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;
  }

  ClassMember? getDispatchTarget(Name name, bool isSetter) {
    return isSetter ? classSetterMap[name] : classMemberMap[name];
  }

  static int compareMaxInheritancePath(
      ClassHierarchyNode a, ClassHierarchyNode b) {
    return b.maxInheritancePath.compareTo(a.maxInheritancePath);
  }
}

class ClassHierarchyNodeDataForTesting {
  final List<ClassMember> abstractMembers;
  final Map<ClassMember, Set<ClassMember>> declaredOverrides;
  final Map<ClassMember, Set<ClassMember>> mixinApplicationOverrides;
  final Map<ClassMember, Set<ClassMember>> inheritedImplements;
  final Map<ClassMember, ClassMember> aliasMap = {};

  ClassHierarchyNodeDataForTesting(this.abstractMembers, this.declaredOverrides,
      this.mixinApplicationOverrides, this.inheritedImplements);
}

List<LocatedMessage> _inheritedConflictContext(ClassMember a, ClassMember b) {
  int length = a.fullNameForErrors.length;
  // TODO(ahe): Delete this method when it isn't used by [InterfaceResolver].
  int compare = "${a.fileUri}".compareTo("${b.fileUri}");
  if (compare == 0) {
    compare = a.charOffset.compareTo(b.charOffset);
  }
  ClassMember first;
  ClassMember second;
  if (compare < 0) {
    first = a;
    second = b;
  } else {
    first = b;
    second = a;
  }
  return <LocatedMessage>[
    messageInheritedMembersConflictCause1.withLocation(
        first.fileUri, first.charOffset, length),
    messageInheritedMembersConflictCause2.withLocation(
        second.fileUri, second.charOffset, length),
  ];
}

class BuilderMixinInferrer extends MixinInferrer {
  final ClassBuilder cls;

  BuilderMixinInferrer(
      this.cls, CoreTypes coreTypes, TypeBuilderConstraintGatherer gatherer)
      : super(coreTypes, gatherer);

  Supertype? asInstantiationOf(Supertype type, Class superclass) {
    List<DartType>? arguments =
        gatherer.getTypeArgumentsAsInstanceOf(type.asInterfaceType, superclass);
    if (arguments == null) return null;
    return new Supertype(superclass, arguments);
  }

  void reportProblem(Message message, Class kernelClass) {
    int length = cls.isMixinApplication ? 1 : cls.fullNameForErrors.length;
    cls.addProblem(message, cls.charOffset, length);
  }
}

class TypeBuilderConstraintGatherer extends TypeConstraintGatherer
    with StandardBounds, TypeSchemaStandardBounds {
  final ClassHierarchyBuilder hierarchy;

  TypeBuilderConstraintGatherer(this.hierarchy,
      Iterable<TypeParameter> typeParameters, Library currentLibrary)
      : super.subclassing(typeParameters, currentLibrary);

  @override
  CoreTypes get coreTypes => hierarchy.coreTypes;

  @override
  void addLowerBound(
      TypeConstraint constraint, DartType lower, Library clientLibrary) {
    constraint.lower =
        getStandardUpperBound(constraint.lower, lower, clientLibrary);
  }

  @override
  void addUpperBound(
      TypeConstraint constraint, DartType upper, Library clientLibrary) {
    constraint.upper =
        getStandardLowerBound(constraint.upper, upper, clientLibrary);
  }

  @override
  Member? getInterfaceMember(Class class_, Name name, {bool setter: false}) {
    return null;
  }

  @override
  InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass,
      Library clientLibrary, CoreTypes coreTypes) {
    return hierarchy.getTypeAsInstanceOf(type, superclass, clientLibrary);
  }

  @override
  List<DartType>? getTypeArgumentsAsInstanceOf(
      InterfaceType type, Class superclass) {
    return hierarchy.getTypeArgumentsAsInstanceOf(type, superclass);
  }

  @override
  InterfaceType futureType(DartType type, Nullability nullability) {
    return new InterfaceType(
        hierarchy.futureClass, nullability, <DartType>[type]);
  }

  @override
  bool isSubtypeOf(
      DartType subtype, DartType supertype, SubtypeCheckMode mode) {
    return hierarchy.types.isSubtypeOf(subtype, supertype, mode);
  }

  @override
  bool areMutualSubtypes(DartType s, DartType t, SubtypeCheckMode mode) {
    return isSubtypeOf(s, t, mode) && isSubtypeOf(t, s, mode);
  }
}

abstract class DelayedCheck {
  void check(ClassHierarchyBuilder hierarchy);
}

class DelayedOverrideCheck implements DelayedCheck {
  final SourceClassBuilder _classBuilder;
  final ClassMember _declaredMember;
  final Set<ClassMember> _overriddenMembers;

  DelayedOverrideCheck(
      this._classBuilder, this._declaredMember, this._overriddenMembers);

  void check(ClassHierarchyBuilder hierarchy) {
    Member declaredMember = _declaredMember.getMember(hierarchy);

    /// If [_declaredMember] is a class member that is declared in an opt-in
    /// library but inherited to [_classBuilder] through an opt-out class then
    /// we need to apply legacy erasure to the declared type to get the
    /// inherited type.
    ///
    /// For interface members this is handled by member signatures but since
    /// these are abstract they will never be the inherited class member.
    ///
    /// For instance:
    ///
    ///    // Opt in:
    ///    class Super {
    ///      int extendedMethod(int i, {required int j}) => i;
    ///    }
    ///    class Mixin {
    ///      int mixedInMethod(int i, {required int j}) => i;
    ///    }
    ///    // Opt out:
    ///    class Legacy extends Super with Mixin {}
    ///    // Opt in:
    ///    class Class extends Legacy {
    ///      // Valid overrides since the type of `Legacy.extendedMethod` is
    ///      // `int* Function(int*, {int* j})`.
    ///      int? extendedMethod(int? i, {int? j}) => i;
    ///      // Valid overrides since the type of `Legacy.mixedInMethod` is
    ///      // `int* Function(int*, {int* j})`.
    ///      int? mixedInMethod(int? i, {int? j}) => i;
    ///    }
    ///
    bool declaredNeedsLegacyErasure =
        needsLegacyErasure(_classBuilder.cls, declaredMember.enclosingClass!);
    void callback(Member interfaceMember, bool isSetter) {
      _classBuilder.checkOverride(
          hierarchy.types, declaredMember, interfaceMember, isSetter, callback,
          isInterfaceCheck: !_classBuilder.isMixinApplication,
          declaredNeedsLegacyErasure: declaredNeedsLegacyErasure);
    }

    for (ClassMember overriddenMember in _overriddenMembers) {
      callback(overriddenMember.getMember(hierarchy), _declaredMember.isSetter);
    }
  }
}

class DelayedGetterSetterCheck implements DelayedCheck {
  final SourceClassBuilder classBuilder;
  final ClassMember getter;
  final ClassMember setter;

  const DelayedGetterSetterCheck(this.classBuilder, this.getter, this.setter);

  void check(ClassHierarchyBuilder hierarchy) {
    classBuilder.checkGetterSetter(hierarchy.types, getter.getMember(hierarchy),
        setter.getMember(hierarchy));
  }
}

class DelayedTypeComputation {
  final ClassHierarchyNodeBuilder builder;
  final ClassMember declaredMember;
  final Set<ClassMember> overriddenMembers;
  bool _computed = false;

  DelayedTypeComputation(
      this.builder, this.declaredMember, this.overriddenMembers)
      : assert(declaredMember.isSourceDeclaration);

  void compute(ClassHierarchyBuilder hierarchy) {
    if (_computed) return;
    declaredMember.inferType(hierarchy);
    _computed = true;
    if (declaredMember.isField) {
      builder.inferFieldSignature(hierarchy, declaredMember, overriddenMembers);
    } else if (declaredMember.isGetter) {
      builder.inferGetterSignature(
          hierarchy, declaredMember, overriddenMembers);
    } else if (declaredMember.isSetter) {
      builder.inferSetterSignature(
          hierarchy, declaredMember, overriddenMembers);
    } else {
      builder.inferMethodSignature(
          hierarchy, declaredMember, overriddenMembers);
    }
  }

  @override
  String toString() => 'DelayedTypeComputation('
      '${builder.classBuilder.name},$declaredMember,$overriddenMembers)';
}

int compareNamedParameters(VariableDeclaration a, VariableDeclaration b) {
  return a.name!.compareTo(b.name!);
}

void reportCantInferParameterType(
    ClassBuilder cls,
    FormalParameterBuilder parameter,
    ClassHierarchyBuilder hierarchy,
    Iterable<ClassMember> overriddenMembers) {
  String name = parameter.name;
  List<LocatedMessage> context = overriddenMembers
      .map((ClassMember overriddenMember) {
        return messageDeclaredMemberConflictsWithOverriddenMembersCause
            .withLocation(overriddenMember.fileUri, overriddenMember.charOffset,
                overriddenMember.fullNameForErrors.length);
      })
      // Call toSet to avoid duplicate context for instance of fields that are
      // overridden both as getters and setters.
      .toSet()
      .toList();
  cls.addProblem(
      templateCantInferTypeDueToNoCombinedSignature.withArguments(name),
      parameter.charOffset,
      name.length,
      wasHandled: true,
      context: context);
}

void reportCantInferTypes(ClassBuilder cls, SourceProcedureBuilder member,
    ClassHierarchyBuilder hierarchy, Iterable<ClassMember> overriddenMembers) {
  String name = member.fullNameForErrors;
  List<LocatedMessage> context = overriddenMembers
      .map((ClassMember overriddenMember) {
        return messageDeclaredMemberConflictsWithOverriddenMembersCause
            .withLocation(overriddenMember.fileUri, overriddenMember.charOffset,
                overriddenMember.fullNameForErrors.length);
      })
      // Call toSet to avoid duplicate context for instance of fields that are
      // overridden both as getters and setters.
      .toSet()
      .toList();
  cls.addProblem(
      templateCantInferTypesDueToNoCombinedSignature.withArguments(name),
      member.charOffset,
      name.length,
      wasHandled: true,
      context: context);
}

void reportCantInferReturnType(ClassBuilder cls, SourceProcedureBuilder member,
    ClassHierarchyBuilder hierarchy, Iterable<ClassMember> overriddenMembers) {
  String name = member.fullNameForErrors;
  List<LocatedMessage> context = overriddenMembers
      .map((ClassMember overriddenMember) {
        return messageDeclaredMemberConflictsWithOverriddenMembersCause
            .withLocation(overriddenMember.fileUri, overriddenMember.charOffset,
                overriddenMember.fullNameForErrors.length);
      })
      // Call toSet to avoid duplicate context for instance of fields that are
      // overridden both as getters and setters.
      .toSet()
      .toList();
  // // TODO(ahe): The following is for debugging, but could be cleaned up and
  // // used to improve this error message in general.
  //
  // context = <LocatedMessage>[];
  // ClassHierarchyNode supernode = hierarchy.getNodeFromType(cls.supertype);
  // // TODO(ahe): Wrong template.
  // Template<Message Function(String)> template =
  //     templateMissingImplementationCause;
  // if (supernode != null) {
  //   Declaration superMember =
  //       supernode.getInterfaceMember(new Name(name), false);
  //   if (superMember != null) {
  //     context.add(template
  //         .withArguments(name)
  //         .withLocation(
  //             superMember.fileUri, superMember.charOffset, name.length));
  //   }
  //   superMember = supernode.getInterfaceMember(new Name(name), true);
  //   if (superMember != null) {
  //     context.add(template
  //         .withArguments(name)
  //         .withLocation(
  //             superMember.fileUri, superMember.charOffset, name.length));
  //   }
  // }
  // List<TypeBuilder> directInterfaces = cls.interfaces;
  // for (int i = 0; i < directInterfaces.length; i++) {
  //   ClassHierarchyNode supernode =
  //       hierarchy.getNodeFromType(directInterfaces[i]);
  //   if (supernode != null) {
  //     Declaration superMember =
  //         supernode.getInterfaceMember(new Name(name), false);
  //     if (superMember != null) {
  //       context.add(template
  //           .withArguments(name)
  //           .withLocation(
  //               superMember.fileUri, superMember.charOffset, name.length));
  //     }
  //     superMember = supernode.getInterfaceMember(new Name(name), true);
  //     if (superMember != null) {
  //       context.add(template
  //           .withArguments(name)
  //           .withLocation(
  //               superMember.fileUri, superMember.charOffset, name.length));
  //     }
  //   }
  // }
  cls.addProblem(
      templateCantInferReturnTypeDueToNoCombinedSignature.withArguments(name),
      member.charOffset,
      name.length,
      wasHandled: true,
      context: context);
}

void reportCantInferFieldType(ClassBuilder cls, SourceFieldBuilder member,
    Iterable<ClassMember> overriddenMembers) {
  List<LocatedMessage> context = overriddenMembers
      .map((ClassMember overriddenMember) {
        return messageDeclaredMemberConflictsWithOverriddenMembersCause
            .withLocation(overriddenMember.fileUri, overriddenMember.charOffset,
                overriddenMember.fullNameForErrors.length);
      })
      // Call toSet to avoid duplicate context for instance of fields that are
      // overridden both as getters and setters.
      .toSet()
      .toList();
  String name = member.fullNameForErrors;
  cls.addProblem(
      templateCantInferTypeDueToNoCombinedSignature.withArguments(name),
      member.charOffset,
      name.length,
      wasHandled: true,
      context: context);
}

ClassBuilder? getClass(TypeBuilder type) {
  Builder? declaration = type.declaration;
  if (declaration is TypeAliasBuilder) {
    TypeAliasBuilder aliasBuilder = declaration;
    NamedTypeBuilder namedBuilder = type as NamedTypeBuilder;
    declaration = aliasBuilder.unaliasDeclaration(namedBuilder.arguments);
  }
  return declaration is ClassBuilder ? declaration : null;
}

Set<ClassMember> toSet(
    ClassBuilder classBuilder, Iterable<ClassMember> members) {
  Set<ClassMember> result = <ClassMember>{};
  _toSet(classBuilder, members, result);
  return result;
}

void _toSet(ClassBuilder classBuilder, Iterable<ClassMember> members,
    Set<ClassMember> result) {
  for (ClassMember member in members) {
    if (member.hasDeclarations && classBuilder == member.classBuilder) {
      _toSet(classBuilder, member.declarations, result);
    } else {
      result.add(member);
    }
  }
}

Set<ClassMember> unfoldDeclarations(Iterable<ClassMember> members) {
  Set<ClassMember> result = <ClassMember>{};
  _unfoldDeclarations(members, result);
  return result;
}

void _unfoldDeclarations(
    Iterable<ClassMember> members, Set<ClassMember> result) {
  for (ClassMember member in members) {
    if (member.hasDeclarations) {
      _unfoldDeclarations(member.declarations, result);
    } else {
      result.add(member);
    }
  }
}

abstract class SynthesizedMember extends ClassMember {
  @override
  final ClassBuilder classBuilder;

  @override
  final Name name;

  @override
  final bool forSetter;

  @override
  final bool isProperty;

  SynthesizedMember(this.classBuilder, this.name,
      {required this.forSetter, required this.isProperty})
      // ignore: unnecessary_null_comparison
      : assert(forSetter != null),
        // ignore: unnecessary_null_comparison
        assert(isProperty != null);

  @override
  List<ClassMember> get declarations => throw new UnimplementedError();

  @override
  void inferType(ClassHierarchyBuilder hierarchy) {}

  @override
  bool get isAssignable => throw new UnimplementedError();

  @override
  bool get isConst => throw new UnimplementedError();

  @override
  bool get isDuplicate => false;

  @override
  bool get isField => throw new UnimplementedError();

  @override
  bool get isFinal => throw new UnimplementedError();

  @override
  bool get isGetter => throw new UnimplementedError();

  @override
  bool get isInternalImplementation => false;

  @override
  bool get isSetter => forSetter;

  @override
  bool get isSourceDeclaration => false;

  @override
  bool get isStatic => false;

  @override
  bool get isSynthesized => true;

  @override
  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {}
}

/// Class member for a set of interface members.
///
/// This is used to compute combined member signature of a set of interface
/// members inherited into the same class, and to insert forwarding stubs,
/// mixin stubs, and member signatures where needed.
class SynthesizedInterfaceMember extends SynthesizedMember {
  @override
  final List<ClassMember> declarations;

  /// The concrete member in the super class overridden by [declarations], if
  /// any.
  ///
  /// This is used to as the target when creating concrete forwarding and mixin
  /// stub. For instance:
  ///
  ///    class Super {
  ///      method(int i) {}
  ///    }
  ///    class Interface {
  ///      method(covariant int i) {}
  ///    }
  ///    class Class extends Super implements Interface {
  ///      // Concrete forwarding stub calling [_superClassMember]:
  ///      method(covariant int i) => super.method(i);
  ///
  final ClassMember? _superClassMember;

  /// The canonical member of the combined member signature if it is known by
  /// construction. The canonical member defines the type of combined member
  /// signature.
  ///
  /// This is used when a declared member is part of a set of implemented
  /// members. For instance
  ///
  ///     class Super {
  ///       method(int i) {}
  ///     }
  ///     class Interface {
  ///       method(covariant num i) {}
  ///     }
  ///     class Class implements Interface {
  ///       // This member is updated to be a concrete forwarding stub with an
  ///       // covariant parameter but with its declared parameter type:
  ///       //    method(covariant int i) => super.method(i);
  ///       method(int i);
  ///     }
  final ClassMember? _canonicalMember;

  /// The member in [declarations] that is mixed in, if any.
  ///
  /// This is used to create mixin stubs. If the mixed in member is abstract,
  /// an abstract mixin stub is created:
  ///
  ///    class Super {
  ///      void method() {}
  ///    }
  ///    class Mixin {
  ///      void method();
  ///    }
  ///    // Abstract mixin stub with `Mixin.method` as target inserted:
  ///    //   void method();
  ///    class Class = Super with Mixin;
  ///
  /// If the mixed in member is concrete, a concrete mixin member is created:
  ///
  ///    class Super {
  ///      void method() {}
  ///    }
  ///    class Mixin {
  ///      void method() {}
  ///    }
  ///    // Concrete mixin stub with `Mixin.method` as target inserted:
  ///    //   void method() => super.method();
  ///    class Class = Super with Mixin;
  ///
  /// If a forwarding stub is needed, the created stub will be a possibly
  /// concrete forwarding stub:
  ///
  ///    class Super {
  ///      void method(int i) {}
  ///    }
  ///    class Interface {
  ///      void method(covariant num i) {}
  ///    }
  ///    class Mixin {
  ///      void method(int i);
  ///    }
  ///    // Concrete forwarding stub with `Super.method` as target inserted:
  ///    //   void method(covariant int i) => super.method(i);
  ///    class Class = Super with Mixin implements Interface;
  ///
  final ClassMember? _mixedInMember;

  /// If `true`, a stub should be inserted, if needed.
  final bool _shouldModifyKernel;

  Member? _member;
  Covariance? _covariance;

  SynthesizedInterfaceMember(
      ClassBuilder classBuilder, Name name, this.declarations,
      {ClassMember? superClassMember,
      ClassMember? canonicalMember,
      ClassMember? mixedInMember,
      required bool isProperty,
      required bool forSetter,
      required bool shouldModifyKernel})
      : this._superClassMember = superClassMember,
        this._canonicalMember = canonicalMember,
        this._mixedInMember = mixedInMember,
        this._shouldModifyKernel = shouldModifyKernel,
        super(classBuilder, name, isProperty: isProperty, forSetter: forSetter);

  @override
  bool get hasDeclarations => true;

  void _ensureMemberAndCovariance(ClassHierarchyBuilder hierarchy) {
    if (_member != null) {
      return;
    }
    if (classBuilder.library is! SourceLibraryBuilder) {
      if (_canonicalMember != null) {
        _member = _canonicalMember!.getMember(hierarchy);
        _covariance = _canonicalMember!.getCovariance(hierarchy);
      } else {
        _member = declarations.first.getMember(hierarchy);
        _covariance = declarations.first.getCovariance(hierarchy);
      }
      return;
    }
    CombinedClassMemberSignature combinedMemberSignature;
    if (_canonicalMember != null) {
      combinedMemberSignature = new CombinedClassMemberSignature.internal(
          hierarchy,
          classBuilder as SourceClassBuilder,
          declarations.indexOf(_canonicalMember!),
          declarations,
          forSetter: isSetter);
    } else {
      combinedMemberSignature = new CombinedClassMemberSignature(
          hierarchy, classBuilder as SourceClassBuilder, declarations,
          forSetter: isSetter);

      if (combinedMemberSignature.canonicalMember == null) {
        String name = classBuilder.fullNameForErrors;
        int length = classBuilder.isAnonymousMixinApplication ? 1 : name.length;
        List<LocatedMessage> context = declarations.map((ClassMember d) {
          return messageDeclaredMemberConflictsWithOverriddenMembersCause
              .withLocation(
                  d.fileUri, d.charOffset, d.fullNameForErrors.length);
        }).toList();

        classBuilder.addProblem(
            templateCombinedMemberSignatureFailed.withArguments(
                classBuilder.fullNameForErrors,
                declarations.first.fullNameForErrors),
            classBuilder.charOffset,
            length,
            context: context);
        // TODO(johnniwinther): Maybe we should have an invalid marker to avoid
        // cascading errors.
        _member = declarations.first.getMember(hierarchy);
        _covariance = declarations.first.getCovariance(hierarchy);
        return;
      }
    }

    if (_shouldModifyKernel) {
      ProcedureKind kind = ProcedureKind.Method;
      Member canonicalMember =
          combinedMemberSignature.canonicalMember!.getMember(hierarchy);
      if (combinedMemberSignature.canonicalMember!.isProperty) {
        kind = isSetter ? ProcedureKind.Setter : ProcedureKind.Getter;
      } else if (canonicalMember is Procedure &&
          canonicalMember.kind == ProcedureKind.Operator) {
        kind = ProcedureKind.Operator;
      }

      Procedure? stub = new ForwardingNode(
              combinedMemberSignature, kind, _superClassMember, _mixedInMember)
          .finalize();
      if (stub != null) {
        assert(classBuilder.cls == stub.enclosingClass);
        assert(stub != canonicalMember);
        classBuilder.cls.addProcedure(stub);
        SourceLibraryBuilder library =
            classBuilder.library as SourceLibraryBuilder;
        if (canonicalMember is Procedure) {
          library.forwardersOrigins..add(stub)..add(canonicalMember);
        }
        _member = stub;
        _covariance = combinedMemberSignature.combinedMemberSignatureCovariance;
        assert(
            _covariance ==
                new Covariance.fromMember(_member!, forSetter: forSetter),
            "Unexpected covariance for combined members signature "
            "$_member. Found $_covariance, expected "
            "${new Covariance.fromMember(_member!, forSetter: forSetter)}.");
        return;
      }
    }

    _member = combinedMemberSignature.canonicalMember!.getMember(hierarchy);
    _covariance = combinedMemberSignature.combinedMemberSignatureCovariance;
  }

  @override
  Member getMember(ClassHierarchyBuilder hierarchy) {
    _ensureMemberAndCovariance(hierarchy);
    return _member!;
  }

  @override
  Covariance getCovariance(ClassHierarchyBuilder hierarchy) {
    _ensureMemberAndCovariance(hierarchy);
    return _covariance!;
  }

  @override
  ClassMember get interfaceMember => this;

  @override
  bool isObjectMember(ClassBuilder objectClass) {
    return false;
  }

  @override
  bool isSameDeclaration(ClassMember other) {
    // TODO(johnniwinther): Optimize this.
    return false;
  }

  @override
  int get charOffset => declarations.first.charOffset;

  @override
  Uri get fileUri => declarations.first.fileUri;

  @override
  bool get isAbstract => true;

  @override
  String get fullNameForErrors =>
      declarations.map((ClassMember m) => m.fullName).join("%");

  @override
  String get fullName {
    String suffix = isSetter ? "=" : "";
    return "${fullNameForErrors}$suffix";
  }

  String toString() => 'SynthesizedInterfaceMember($classBuilder,$name,'
      '$declarations,forSetter=$forSetter)';
}

/// Class member for an inherited concrete member that implements an interface
/// member.
///
/// This is used to ensure that both the inherited concrete member and the
/// interface member is taken into account when computing the resulting [Member]
/// node.
///
/// This is needed because an interface member, though initially abstract, can
/// result in a concrete stub that overrides the concrete member. For instance
///
///    class Super {
///      method(int i) {}
///    }
///    class Interface {
///      method(covariant int i) {}
///    }
///    class Class extends Super implements Interface {
///      // A concrete forwarding stub is inserted:
///      method(covariant int i) => super.method(i);
///    }
///    class Sub extends Class implements Interface {
///      // No forwarding stub should be inserted since `Class.method` is
///      // adequate.
///    }
///
///
///  Here the create stub `Class.method` overrides `Super.method` and should
///  be used to determine whether to insert a forwarding stub in subclasses.
class InheritedClassMemberImplementsInterface extends SynthesizedMember {
  final ClassMember inheritedClassMember;
  final ClassMember implementedInterfaceMember;

  Member? _member;
  Covariance? _covariance;

  InheritedClassMemberImplementsInterface(ClassBuilder classBuilder, Name name,
      {required this.inheritedClassMember,
      required this.implementedInterfaceMember,
      required bool isProperty,
      required bool forSetter})
      // ignore: unnecessary_null_comparison
      : assert(inheritedClassMember != null),
        // ignore: unnecessary_null_comparison
        assert(implementedInterfaceMember != null),
        super(classBuilder, name, isProperty: isProperty, forSetter: forSetter);

  void _ensureMemberAndCovariance(ClassHierarchyBuilder hierarchy) {
    if (_member == null) {
      Member classMember = inheritedClassMember.getMember(hierarchy);
      Member interfaceMember = implementedInterfaceMember.getMember(hierarchy);
      if (!interfaceMember.isAbstract &&
          interfaceMember.enclosingClass == classBuilder.cls) {
        /// The interface member resulted in a concrete stub being inserted.
        /// For instance for `method1` but _not_ for `method2` here:
        ///
        ///    class Super {
        ///      method1(int i) {}
        ///      method2(covariant int i) {}
        ///    }
        ///    class Interface {
        ///      method1(covariant int i) {}
        ///      method2(int i) {}
        ///    }
        ///    class Class extends Super implements Interface {
        ///      // A concrete forwarding stub is inserted for `method1` since
        ///      // the parameter on `Super.method1` is _not_ marked as
        ///      // covariant:
        ///      method1(covariant int i) => super.method(i);
        ///      // No concrete forwarding stub is inserted for `method2` since
        ///      // the parameter on `Super.method2` is already marked as
        ///      // covariant.
        ///    }
        ///
        /// The inserted stub should be used as the resulting member.
        _member = interfaceMember;
        _covariance = implementedInterfaceMember.getCovariance(hierarchy);
      } else {
        /// The interface member did not result in an inserted stub or the
        /// inserted stub was abstract. For instance:
        ///
        ///    // Opt-in:
        ///    class Super {
        ///      method(int? i) {}
        ///    }
        ///    // Opt-out:
        ///    class Class extends Super {
        ///      // An abstract member signature stub is inserted:
        ///      method(int* i);
        ///    }
        ///
        /// The inserted stub should _not_ be used as the resulting member
        /// since it is abstract and therefore not a class member.
        _member = classMember;
        _covariance = inheritedClassMember.getCovariance(hierarchy);
      }
    }
  }

  @override
  Member getMember(ClassHierarchyBuilder hierarchy) {
    _ensureMemberAndCovariance(hierarchy);
    return _member!;
  }

  @override
  Covariance getCovariance(ClassHierarchyBuilder hierarchy) {
    _ensureMemberAndCovariance(hierarchy);
    return _covariance!;
  }

  @override
  ClassMember get interfaceMember => implementedInterfaceMember;

  @override
  bool isObjectMember(ClassBuilder objectClass) {
    return inheritedClassMember.isObjectMember(objectClass);
  }

  @override
  bool isSameDeclaration(ClassMember other) {
    // TODO(johnniwinther): Optimize this.
    return false;
  }

  @override
  int get charOffset => inheritedClassMember.charOffset;

  @override
  Uri get fileUri => inheritedClassMember.fileUri;

  @override
  bool get hasDeclarations => false;

  @override
  bool get isAbstract => false;

  @override
  String get fullNameForErrors => inheritedClassMember.fullNameForErrors;

  String get fullName => inheritedClassMember.fullName;

  @override
  String toString() =>
      'InheritedClassMemberImplementsInterface($classBuilder,$name,'
      'inheritedClassMember=$inheritedClassMember,'
      'implementedInterfaceMember=$implementedInterfaceMember,'
      'forSetter=$forSetter)';
}
