[cfe] Remove use of the AST-based class hierarchy from the inferrer

Change-Id: I636dd75b443a23dc531fbeddfbbf3cb76358e5f0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/269780
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther 2022-11-15 10:44:10 +00:00 committed by Commit Queue
parent 50e18b8160
commit 39c68314f2
12 changed files with 122 additions and 109 deletions

View file

@ -78,6 +78,7 @@ class ClassHierarchyBuilder implements ClassHierarchyBase {
@override
Supertype? getClassAsInstanceOf(Class subclass, Class superclass) {
if (identical(subclass, superclass)) return subclass.asThisSupertype;
ClassHierarchyNode clsNode = getNodeFromClass(subclass);
ClassHierarchyNode supertypeNode = getNodeFromClass(superclass);
List<Supertype> superclasses = clsNode.superclasses;
@ -114,6 +115,11 @@ class ClassHierarchyBuilder implements ClassHierarchyBase {
return asSupertypeOf(type, superclass)?.typeArguments;
}
@override
bool isSubtypeOf(Class subtype, Class superclass) {
return getClassAsInstanceOf(subtype, superclass) != null;
}
@override
InterfaceType getLegacyLeastUpperBound(
InterfaceType type1, InterfaceType type2, Library clientLibrary) {

View file

@ -148,6 +148,18 @@ class ClassMembersBuilder implements ClassHierarchyMembers {
return getNodeFromClass(cls).getInterfaceMember(name, setter);
}
@override
Member? getDispatchTarget(Class cls, Name name, {bool setter = false}) {
return getNodeFromClass(cls)
.getDispatchTarget(name, setter)
?.getMember(this);
}
ClassMember? getDispatchClassMember(Class cls, Name name,
{bool setter = false}) {
return getNodeFromClass(cls).getDispatchTarget(name, setter);
}
static ClassMembersBuilder build(
ClassHierarchyBuilder hierarchyBuilder, List<ClassBuilder> classes) {
ClassMembersBuilder membersBuilder =

View file

@ -74,14 +74,6 @@ class ClassMembersNodeBuilder {
bool get shouldModifyKernel =>
classBuilder.libraryBuilder.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 hierarchyBuilder,
ClassMembersBuilder membersBuilder,
@ -2311,6 +2303,7 @@ class ClassMembersNodeBuilder {
return new ClassMembersNode(
classBuilder,
supernode,
classMemberMap,
classSetterMap,
interfaceMemberMap,
@ -2360,6 +2353,8 @@ class ClassMembersNodeBuilder {
class ClassMembersNode {
final ClassBuilder classBuilder;
final ClassMembersNode? supernode;
/// All the members of this class including [classMembers] of its
/// superclasses. The members are sorted by [compareDeclarations].
final Map<Name, ClassMember> classMemberMap;
@ -2387,6 +2382,7 @@ class ClassMembersNode {
ClassMembersNode(
this.classBuilder,
this.supernode,
this.classMemberMap,
this.classSetterMap,
this.interfaceMemberMap,
@ -2434,9 +2430,16 @@ class ClassMembersNode {
}
ClassMember? getInterfaceMember(Name name, bool isSetter) {
return isSetter
ClassMember? result = isSetter
? (interfaceSetterMap ?? classSetterMap)[name]
: (interfaceMemberMap ?? classMemberMap)[name];
if (result == null) {
return null;
}
if (result.isStatic) {
return null;
}
return result;
}
ClassMember? findMember(Name name, List<ClassMember> declarations) {
@ -2464,7 +2467,17 @@ class ClassMembersNode {
}
ClassMember? getDispatchTarget(Name name, bool isSetter) {
return isSetter ? classSetterMap[name] : classMemberMap[name];
ClassMember? result =
isSetter ? classSetterMap[name] : classMemberMap[name];
if (result == null) {
return null;
}
if (result.isStatic) {
// TODO(johnniwinther): Can we avoid putting static members in the
// [classMemberMap]/[classSetterMap] maps?
return supernode?.getDispatchTarget(name, isSetter);
}
return result;
}
}

View file

@ -12,7 +12,8 @@ import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
import 'package:_fe_analyzer_shared/src/util/resolve_relative_uri.dart'
show resolveRelativeUri;
import 'package:kernel/ast.dart' hide Combinator, MapLiteralEntry;
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/class_hierarchy.dart'
show ClassHierarchy, ClassHierarchyBase, ClassHierarchyMembers;
import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
import 'package:kernel/reference_from_index.dart'
show IndexedClass, IndexedContainer, IndexedLibrary;
@ -4416,7 +4417,8 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
void checkBoundsInMethodInvocation(
DartType receiverType,
TypeEnvironment typeEnvironment,
ClassHierarchy hierarchy,
ClassHierarchyBase classHierarchy,
ClassHierarchyMembers membersHierarchy,
Name name,
Member? interfaceTarget,
Arguments arguments,
@ -4437,14 +4439,14 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
}
// TODO(cstefantsova): Find a better way than relying on [interfaceTarget].
Member? method =
hierarchy.getDispatchTarget(klass, name) ?? interfaceTarget;
membersHierarchy.getDispatchTarget(klass, name) ?? interfaceTarget;
// ignore: unnecessary_null_comparison
if (method == null || method is! Procedure) {
return;
}
if (klass != method.enclosingClass) {
Supertype parent =
hierarchy.getClassAsInstanceOf(klass, method.enclosingClass!)!;
classHierarchy.getClassAsInstanceOf(klass, method.enclosingClass!)!;
klass = method.enclosingClass!;
receiverTypeArguments = parent.typeArguments;
Map<TypeParameter, DartType> instanceSubstitutionMap = substitutionMap;
@ -4492,7 +4494,6 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
void checkBoundsInFunctionInvocation(
TypeEnvironment typeEnvironment,
ClassHierarchy hierarchy,
FunctionType functionType,
String? localName,
Arguments arguments,
@ -4526,7 +4527,6 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
void checkBoundsInInstantiation(
TypeEnvironment typeEnvironment,
ClassHierarchy hierarchy,
FunctionType functionType,
List<DartType> typeArguments,
Uri fileUri,

View file

@ -2295,21 +2295,25 @@ severity: $severity
Name name = restrictedMemberNames[i];
Class? declarer = restrictedMemberDeclarers[i];
Member? member = hierarchy.getDispatchTarget(classBuilder.cls, name);
if (member?.enclosingClass != declarer &&
member?.enclosingClass != classBuilder.cls &&
member?.isAbstract == false) {
classBuilder.libraryBuilder.addProblem(
templateEnumInheritsRestricted.withArguments(name.text),
classBuilder.charOffset,
classBuilder.name.length,
classBuilder.fileUri,
context: <LocatedMessage>[
messageEnumInheritsRestrictedMember.withLocation(
member!.fileUri,
member.fileOffset,
member.name.text.length)
]);
ClassMember? classMember =
membersBuilder.getDispatchClassMember(classBuilder.cls, name);
if (classMember != null) {
Member member = classMember.getMember(membersBuilder);
if (member.enclosingClass != declarer &&
member.enclosingClass != classBuilder.cls &&
member.isAbstract == false) {
classBuilder.libraryBuilder.addProblem(
templateEnumInheritsRestricted.withArguments(name.text),
classBuilder.charOffset,
classBuilder.name.length,
classBuilder.fileUri,
context: <LocatedMessage>[
messageEnumInheritsRestrictedMember.withLocation(
classMember.fileUri,
classMember.charOffset,
member.name.text.length)
]);
}
}
}
}

View file

@ -1407,7 +1407,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
if (inferredExpressionType is InterfaceType) {
// TODO(johnniwinther): Should we use the type of
// `iterable.iterator.current` instead?
List<DartType>? supertypeArguments = classHierarchy
List<DartType>? supertypeArguments = hierarchyBuilder
.getTypeArgumentsAsInstanceOf(inferredExpressionType, iterableClass);
if (supertypeArguments != null) {
inferredType = supertypeArguments[0];
@ -1636,7 +1636,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
InitializerInferenceResult visitInvalidSuperInitializerJudgment(
InvalidSuperInitializerJudgment node) {
Substitution substitution = Substitution.fromSupertype(
classHierarchy.getClassAsInstanceOf(
hierarchyBuilder.getClassAsInstanceOf(
thisType!.classNode, node.target.enclosingClass)!);
FunctionType functionType = replaceReturnType(
substitution.substituteType(node.target.function
@ -2843,10 +2843,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase
// Ambiguous set/map literal
if (unfuturedTypeContext is InterfaceType) {
typeContextIsMap = typeContextIsMap ||
classHierarchy.isSubtypeOf(
hierarchyBuilder.isSubtypeOf(
unfuturedTypeContext.classNode, coreTypes.mapClass);
typeContextIsIterable = typeContextIsIterable ||
classHierarchy.isSubtypeOf(
hierarchyBuilder.isSubtypeOf(
unfuturedTypeContext.classNode, coreTypes.iterableClass);
if (node.entries.isEmpty && typeContextIsIterable && !typeContextIsMap) {
// Set literal
@ -3086,7 +3086,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
result.inferredType, result.applyResult(invocation));
} else {
// TODO(johnniwinther): Handle augmentation of field with inferred types.
TypeInferenceEngine.resolveInferenceNode(member, classHierarchy);
TypeInferenceEngine.resolveInferenceNode(member, hierarchyBuilder);
Link<NullAwareGuard> nullAwareGuards = const Link<NullAwareGuard>();
DartType receiverType = member.getterType;
Expression receiver = new StaticGet(member)..fileOffset = node.fileOffset;
@ -5892,7 +5892,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
return new ExpressionInferenceResult(replacementType, replacement);
} else {
// TODO(johnniwinther): Handle augmentation of field with inferred types.
TypeInferenceEngine.resolveInferenceNode(member, classHierarchy);
TypeInferenceEngine.resolveInferenceNode(member, hierarchyBuilder);
DartType writeContext = member.setterType;
ExpressionInferenceResult rhsResult =
inferExpression(node.value, writeContext, isVoidAllowed: true);
@ -6153,7 +6153,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
readResult.inferredType, readResult.expression);
} else {
// TODO(johnniwinther): Handle augmentation of field with inferred types.
TypeInferenceEngine.resolveInferenceNode(member, classHierarchy);
TypeInferenceEngine.resolveInferenceNode(member, hierarchyBuilder);
DartType type = member.getterType;
if (member is Procedure && member.kind == ProcedureKind.Method) {
@ -6302,7 +6302,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
ExpressionInferenceResult visitStaticSet(
StaticSet node, DartType typeContext) {
Member writeMember = node.target;
TypeInferenceEngine.resolveInferenceNode(writeMember, classHierarchy);
TypeInferenceEngine.resolveInferenceNode(writeMember, hierarchyBuilder);
DartType writeContext = writeMember.setterType;
ExpressionInferenceResult rhsResult =
inferExpression(node.value, writeContext, isVoidAllowed: true);
@ -6318,7 +6318,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
ExpressionInferenceResult visitStaticGet(
StaticGet node, DartType typeContext) {
Member target = node.target;
TypeInferenceEngine.resolveInferenceNode(target, classHierarchy);
TypeInferenceEngine.resolveInferenceNode(target, hierarchyBuilder);
DartType type = target.getterType;
if (!isNonNullableByDefault) {
@ -6378,7 +6378,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
InitializerInferenceResult visitSuperInitializer(SuperInitializer node) {
ensureMemberType(node.target);
Substitution substitution = Substitution.fromSupertype(
classHierarchy.getClassAsInstanceOf(
hierarchyBuilder.getClassAsInstanceOf(
thisType!.classNode, node.target.enclosingClass)!);
FunctionType functionType = replaceReturnType(
substitution.substituteType(node.target.function

View file

@ -9,7 +9,8 @@ import 'package:_fe_analyzer_shared/src/testing/id.dart';
import 'package:_fe_analyzer_shared/src/util/link.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/canonical_name.dart' as kernel;
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/class_hierarchy.dart'
show ClassHierarchyBase, ClassHierarchyMembers;
import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:kernel/src/bounds_checks.dart'
show calculateBounds, isGenericFunctionTypeOrAlias;
@ -32,7 +33,6 @@ import '../builder/extension_builder.dart';
import '../builder/member_builder.dart';
import '../fasta_codes.dart';
import '../kernel/constructor_tearoff_lowering.dart';
import '../kernel/hierarchy/class_member.dart' show ClassMember;
import '../kernel/internal_ast.dart';
import '../kernel/kernel_helper.dart';
import '../kernel/type_algorithms.dart' show hasAnyTypeVariables;
@ -171,7 +171,9 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
Instrumentation? get instrumentation => _inferrer.instrumentation;
ClassHierarchy get classHierarchy => _inferrer.classHierarchy;
ClassHierarchyBase get hierarchyBuilder => _inferrer.engine.hierarchyBuilder;
ClassHierarchyMembers get membersBuilder => _inferrer.engine.membersBuilder;
InferenceDataForTesting? get dataForTesting => _inferrer.dataForTesting;
@ -366,7 +368,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
} else if ((constructor = engine.toBeInferred[target]) != null) {
engine.toBeInferred.remove(target);
engine.beingInferred[target] = constructor!;
constructor.inferFormalTypes(classHierarchy);
constructor.inferFormalTypes(hierarchyBuilder);
engine.beingInferred.remove(target);
}
}
@ -669,7 +671,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
TypedTearoff _tearOffCall(
Expression expression, InterfaceType expressionType, int fileOffset) {
Class classNode = expressionType.classNode;
Member callMember = classHierarchy.getInterfaceMember(classNode, callName)!;
Member callMember = membersBuilder.getInterfaceMember(classNode, callName)!;
assert(callMember is Procedure && callMember.kind == ProcedureKind.Method);
// Replace expression with:
@ -719,7 +721,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
if (coerceExpression && expressionType is InterfaceType) {
Class classNode = expressionType.classNode;
Member? callMember =
classHierarchy.getInterfaceMember(classNode, callName);
membersBuilder.getInterfaceMember(classNode, callName);
if (callMember is Procedure && callMember.kind == ProcedureKind.Method) {
if (_shouldTearOffCall(contextType, expressionType)) {
needsTearoff = true;
@ -851,7 +853,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
if (showHideClause == null) return defaultTarget;
kernel.Reference? reference = showHideClause.findShownReference(
name, callSiteAccessKind, classHierarchy);
name, callSiteAccessKind, membersBuilder);
if (reference != null) {
return new ObjectAccessTarget.interfaceMember(
receiverType, reference.asMember,
@ -1314,7 +1316,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
if (memberClass.typeParameters.isNotEmpty) {
receiverType = resolveTypeParameter(receiverType);
if (receiverType is InterfaceType) {
List<DartType> castedTypeArguments = classHierarchy
List<DartType> castedTypeArguments = hierarchyBuilder
.getTypeArgumentsAsInstanceOf(receiverType, memberClass)!;
calleeType = Substitution.fromPairs(
memberClass.typeParameters, castedTypeArguments)
@ -1367,7 +1369,7 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
DartType? getDerivedTypeArgumentOf(DartType type, Class class_) {
if (type is InterfaceType) {
List<DartType>? typeArgumentsAsInstanceOfClass =
classHierarchy.getTypeArgumentsAsInstanceOf(type, class_);
hierarchyBuilder.getTypeArgumentsAsInstanceOf(type, class_);
if (typeArgumentsAsInstanceOfClass != null) {
return typeArgumentsAsInstanceOfClass[0];
}
@ -3299,7 +3301,8 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
libraryBuilder.checkBoundsInMethodInvocation(
actualReceiverType,
typeSchemaEnvironment,
classHierarchy,
hierarchyBuilder,
membersBuilder,
actualMethodName,
interfaceTarget,
arguments,
@ -3314,22 +3317,16 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
assert(inferred != null);
// If [arguments] were inferred, check them.
libraryBuilder.checkBoundsInInstantiation(typeSchemaEnvironment,
classHierarchy, functionType, arguments, helper.uri, fileOffset,
libraryBuilder.checkBoundsInInstantiation(
typeSchemaEnvironment, functionType, arguments, helper.uri, fileOffset,
inferred: inferred);
}
void _checkBoundsInFunctionInvocation(FunctionType functionType,
String? localName, Arguments arguments, int fileOffset) {
// If [arguments] were inferred, check them.
libraryBuilder.checkBoundsInFunctionInvocation(
typeSchemaEnvironment,
classHierarchy,
functionType,
localName,
arguments,
helper.uri,
fileOffset);
libraryBuilder.checkBoundsInFunctionInvocation(typeSchemaEnvironment,
functionType, localName, arguments, helper.uri, fileOffset);
}
/// Performs the core type inference algorithm for super method invocations.
@ -3635,22 +3632,9 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
Member? _getInterfaceMember(
Class class_, Name name, bool setter, int charOffset) {
ClassMember? classMember = engine.membersBuilder
.getInterfaceClassMember(class_, name, setter: setter);
if (classMember != null) {
if (classMember.isStatic) {
classMember = null;
} else if (classMember.isDuplicate) {
libraryBuilder.addProblem(
templateDuplicatedDeclarationUse.withArguments(name.text),
charOffset,
name.text.length,
helper.uri);
classMember = null;
}
}
Member? member = classMember?.getMember(engine.membersBuilder);
return TypeInferenceEngine.resolveInferenceNode(member, classHierarchy);
Member? member =
engine.membersBuilder.getInterfaceMember(class_, name, setter: setter);
return TypeInferenceEngine.resolveInferenceNode(member, hierarchyBuilder);
}
/// Determines if the given [expression]'s type is precisely known at compile

View file

@ -419,7 +419,7 @@ class InstanceAccessTarget extends ObjectAccessTarget {
if (resolvedReceiverType is InterfaceType) {
setterType = Substitution.fromPairs(
memberClass.typeParameters,
base.classHierarchy.getTypeArgumentsAsInstanceOf(
base.hierarchyBuilder.getTypeArgumentsAsInstanceOf(
resolvedReceiverType, memberClass)!)
.substituteType(setterType);
}

View file

@ -6,7 +6,8 @@ import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
import 'package:_fe_analyzer_shared/src/type_inference/assigned_variables.dart';
import 'package:_fe_analyzer_shared/src/type_inference/type_operations.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/class_hierarchy.dart'
show ClassHierarchy, ClassHierarchyBase;
import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:kernel/type_environment.dart';
@ -133,8 +134,6 @@ class IncludesTypeParametersNonCovariantly implements DartTypeVisitor<bool> {
/// (e.g. DietListener). Derived classes should derive from
/// [TypeInferenceEngineImpl].
abstract class TypeInferenceEngine {
late ClassHierarchy classHierarchy;
late ClassHierarchyBuilder hierarchyBuilder;
late ClassMembersBuilder membersBuilder;
@ -187,7 +186,7 @@ abstract class TypeInferenceEngine {
// Field types have all been inferred so we don't need to guard against
// cyclic dependency.
for (SourceConstructorBuilder builder in toBeInferred.values) {
builder.inferFormalTypes(classHierarchy);
builder.inferFormalTypes(hierarchyBuilder);
}
toBeInferred.clear();
for (TypeDependency typeDependency in typeDependencies.values) {
@ -200,13 +199,12 @@ abstract class TypeInferenceEngine {
/// given [hierarchy], using the given [coreTypes].
void prepareTopLevel(CoreTypes coreTypes, ClassHierarchy hierarchy) {
this.coreTypes = coreTypes;
this.classHierarchy = hierarchy;
this.typeSchemaEnvironment =
new TypeSchemaEnvironment(coreTypes, hierarchy);
}
static Member? resolveInferenceNode(
Member? member, ClassHierarchy hierarchy) {
Member? member, ClassHierarchyBase hierarchy) {
if (member is Field) {
DartType type = member.type;
if (type is InferredType) {

View file

@ -5,7 +5,6 @@
import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
import 'package:_fe_analyzer_shared/src/type_inference/assigned_variables.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import '../../base/instrumentation.dart' show Instrumentation;
import '../kernel/benchmarker.dart' show BenchmarkSubdivides, Benchmarker;
@ -116,8 +115,6 @@ class TypeInferrerImpl implements TypeInferrer {
@override
final bool isTopLevel;
final ClassHierarchy classHierarchy;
final Instrumentation? instrumentation;
@override
@ -140,7 +137,6 @@ class TypeInferrerImpl implements TypeInferrer {
: assert(libraryBuilder != null),
unknownFunction = new FunctionType(
const [], const DynamicType(), libraryBuilder.nonNullable),
classHierarchy = engine.classHierarchy,
instrumentation = isTopLevel ? null : engine.instrumentation,
typeSchemaEnvironment = engine.typeSchemaEnvironment,
operations = new OperationsCfe(engine.typeSchemaEnvironment,

View file

@ -1880,7 +1880,7 @@ class ExtensionTypeShowHideClause {
final List<Reference> hiddenOperators = <Reference>[];
Reference? findShownReference(Name name,
CallSiteAccessKind callSiteAccessKind, ClassHierarchy hierarchy) {
CallSiteAccessKind callSiteAccessKind, ClassHierarchyMembers hierarchy) {
List<Reference> shownReferences;
List<Reference> hiddenReferences;
switch (callSiteAccessKind) {
@ -1918,7 +1918,7 @@ class ExtensionTypeShowHideClause {
Name name,
List<Reference> references,
List<Supertype> interfaces,
ClassHierarchy hierarchy,
ClassHierarchyMembers hierarchy,
CallSiteAccessKind callSiteAccessKind) {
for (Reference reference in references) {
if (reference.asMember.name == name) {

View file

@ -42,6 +42,10 @@ abstract class ClassHierarchyBase {
List<DartType>? getTypeArgumentsAsInstanceOf(
InterfaceType type, Class superclass);
/// True if [subtype] inherits from [superclass] though zero or more
/// `extends`, `with`, and `implements` relationships.
bool isSubtypeOf(Class subtype, Class superclass);
/// Returns the least upper bound of two interface types, as defined by Dart
/// 1.0.
///
@ -62,6 +66,21 @@ abstract class ClassHierarchyBase {
}
abstract class ClassHierarchyMembers {
/// Returns the instance member that would respond to a dynamic dispatch of
/// [name] to an instance of [class_], or `null` if no such member exists.
///
/// If [setter] is `false`, the name is dispatched as a getter or call,
/// and will return a field, getter, method, or operator (or null).
///
/// If [setter] is `true`, the name is dispatched as a setter, roughly
/// corresponding to `name=` in the Dart specification, but note that the
/// returned member will not have a name ending with `=`. In this case,
/// a non-final field or setter (or null) will be returned.
///
/// If the class is abstract, abstract members are ignored and the dispatch
/// is resolved if the class was not abstract.
Member? getDispatchTarget(Class class_, Name name, {bool setter = false});
/// Returns the possibly abstract interface member of [class_] with the given
/// [name].
///
@ -111,21 +130,6 @@ abstract class ClassHierarchy
/// be a generic class.
Supertype? asInstantiationOf(Supertype type, Class superclass);
/// Returns the instance member that would respond to a dynamic dispatch of
/// [name] to an instance of [class_], or `null` if no such member exists.
///
/// If [setter] is `false`, the name is dispatched as a getter or call,
/// and will return a field, getter, method, or operator (or null).
///
/// If [setter] is `true`, the name is dispatched as a setter, roughly
/// corresponding to `name=` in the Dart specification, but note that the
/// returned member will not have a name ending with `=`. In this case,
/// a non-final field or setter (or null) will be returned.
///
/// If the class is abstract, abstract members are ignored and the dispatch
/// is resolved if the class was not abstract.
Member? getDispatchTarget(Class class_, Name name, {bool setter = false});
/// Returns the list of potential targets of dynamic dispatch to an instance
/// of [class_].
///
@ -159,10 +163,6 @@ abstract class ClassHierarchy
/// `extends` relationships.
bool isSubclassOf(Class subclass, Class superclass);
/// True if [subtype] inherits from [superclass] though zero or more
/// `extends`, `with`, and `implements` relationships.
bool isSubtypeOf(Class subtype, Class superclass);
/// True if the given class is used as the right-hand operand to a
/// mixin application (i.e. [Class.mixedInType]).
bool isUsedAsMixin(Class class_);