[analyzer] Change InheritanceManager3 to use Impl types.

The following methods of `InheritanceManager3` are changed so that
their return types refer to Impl classes rather than analyzer public
API classes:

- `combineSignatures`
- `getInherited2`
- `getInheritedMap2`
- `getMember`
- `getMember2`

To reduce the number of type casts this introduces, some of the
parameters and return types of various private methods of
`InheritanceManager3` are also changed to use Impl types, and some
similar changes are made to the inheritance manager's internal data
structures (`Interface` and `_ExtensionTypeCandidates`).

Also, the following new classes are introduced, to act as common base
classes for analyzer-internal classes in situations where no common
base class previously existed:

- `ExecutableElementOrMember` (the common base class for all internal
  classes that implement `ExecutableElement`)

- `PropertyAccessorElementOrMember` (the common base class for all
  internal classes that implement `PropertyAccessorElement`)

- `PropertyInducingElementOrMember` (the common base class for all
  internal classes that implement `PropertyInducingElement`)

- `VariableElement2OrMember` (the common base class for all internal
  classes that implement `VariableElement2`)

- `VariableElementOrMember` (the common base class for all internal
  classes that implement `VariableElement`)

This is part of a larger arc of work to change the analyzer's use of
the shared code so that the type parameters it supplies are not part
of the analyzer public API. See
https://github.com/dart-lang/sdk/issues/59763.

Change-Id: Ib7f20480c1f57af22a0214075e8f0e13c3429340
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/405565
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 5d5027e..9f8d9e3 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1746,7 +1746,8 @@
 }
 
 /// Common implementation for methods defined in [ConstructorElement].
-mixin ConstructorElementMixin implements ConstructorElement {
+mixin ConstructorElementMixin
+    implements ConstructorElement, ExecutableElementOrMember {
   @override
   bool get isDefaultConstructor {
     // unnamed
@@ -3723,7 +3724,7 @@
 /// A base class for concrete implementations of an [ExecutableElement].
 abstract class ExecutableElementImpl extends _ExistingElementImpl
     with TypeParameterizedElementMixin, MacroTargetElement
-    implements ExecutableElement, ExecutableFragment {
+    implements ExecutableElementOrMember, ExecutableFragment {
   /// A list containing all of the parameters defined by this executable
   /// element.
   List<ParameterElementImpl> _parameters = const [];
@@ -3950,6 +3951,16 @@
   }
 }
 
+/// Common base class for all analyzer-internal classes that implement
+/// `ExecutableElement`.
+abstract class ExecutableElementOrMember implements ExecutableElement {
+  @override
+  TypeImpl get returnType;
+
+  @override
+  FunctionTypeImpl get type;
+}
+
 /// A concrete implementation of an [ExtensionElement].
 class ExtensionElementImpl extends InstanceElementImpl
     with AugmentableElement<ExtensionElementImpl>
@@ -4046,7 +4057,7 @@
   }
 
   @override
-  PropertyAccessorElement? getGetter(String getterName) {
+  PropertyAccessorElementOrMember? getGetter(String getterName) {
     for (var accessor in augmented.accessors) {
       if (accessor.isGetter && accessor.name == getterName) {
         return accessor;
@@ -4056,7 +4067,7 @@
   }
 
   @override
-  MethodElement? getMethod(String methodName) {
+  MethodElementOrMember? getMethod(String methodName) {
     for (var method in augmented.methods) {
       if (method.name == methodName) {
         return method;
@@ -4426,7 +4437,7 @@
   SetterElement? get setter2 => firstFragment.setter?.element as SetterElement?;
 
   @override
-  DartType get type => firstFragment.type;
+  TypeImpl get type => firstFragment.type;
 
   @override
   T? accept2<T>(ElementVisitor2<T> visitor) {
@@ -4662,7 +4673,10 @@
 /// A mixin that provides a common implementation for methods defined in
 /// [FormalParameterElement].
 mixin FormalParameterElementMixin
-    implements FormalParameterElement, SharedNamedFunctionParameter {
+    implements
+        FormalParameterElement,
+        SharedNamedFunctionParameter,
+        VariableElement2OrMember {
   @override
   TypeImpl get type;
 
@@ -5157,7 +5171,8 @@
         FunctionElement,
         FunctionTypedElementImpl,
         LocalFunctionFragment,
-        TopLevelFunctionFragment {
+        TopLevelFunctionFragment,
+        ExecutableElementOrMember {
   @override
   String? name2;
 
@@ -5698,10 +5713,10 @@
   List<FieldElement> fields = [];
 
   @override
-  List<PropertyAccessorElement> accessors = [];
+  List<PropertyAccessorElementOrMember> accessors = [];
 
   @override
-  List<MethodElement> methods = [];
+  List<MethodElementOrMember> methods = [];
 
   final List<MethodElementImpl2> internal_methods2 = [];
 
@@ -7734,7 +7749,10 @@
 
 /// A concrete implementation of a [LocalVariableElement].
 class LocalVariableElementImpl extends NonParameterVariableElementImpl
-    implements LocalVariableElement, LocalVariableFragment {
+    implements
+        LocalVariableElement,
+        LocalVariableFragment,
+        VariableElementOrMember {
   late LocalVariableElementImpl2 _element2 = switch (this) {
     BindPatternVariableElementImpl() => BindPatternVariableElementImpl2(this),
     JoinPatternVariableElementImpl() => JoinPatternVariableElementImpl2(this),
@@ -8268,6 +8286,8 @@
   }
 }
 
+/// Common base class for all analyzer-internal classes that implement
+/// `MethodElement2`.
 abstract class MethodElement2OrMember implements MethodElement2 {
   @override
   FunctionTypeImpl get type;
@@ -8433,7 +8453,13 @@
   }
 }
 
-abstract class MethodElementOrMember implements MethodElement {
+/// Common base class for all analyzer-internal classes that implement
+/// `MethodElement`.
+abstract class MethodElementOrMember
+    implements MethodElement, ExecutableElementOrMember {
+  @override
+  TypeImpl get returnType;
+
   @override
   FunctionTypeImpl get type;
 }
@@ -9522,7 +9548,8 @@
 
 /// A mixin that provides a common implementation for methods defined in
 /// [ParameterElement].
-mixin ParameterElementMixin implements ParameterElement {
+mixin ParameterElementMixin
+    implements ParameterElement, VariableElementOrMember {
   @override
   bool get isNamed => parameterKind.isNamed;
 
@@ -9893,7 +9920,7 @@
 class PropertyAccessorElementImpl extends ExecutableElementImpl
     with AugmentableElement<PropertyAccessorElementImpl>
     implements
-        PropertyAccessorElement,
+        PropertyAccessorElementOrMember,
         PropertyAccessorFragment,
         GetterFragment,
         SetterFragment {
@@ -10244,11 +10271,22 @@
   PropertyInducingElementImpl get variable2 => super.variable2!;
 }
 
+/// Common base class for all analyzer-internal classes that implement
+/// `PropertyAccessorElement`.
+abstract class PropertyAccessorElementOrMember
+    implements PropertyAccessorElement, ExecutableElementOrMember {
+  @override
+  TypeImpl get returnType;
+
+  @override
+  PropertyInducingElementOrMember? get variable2;
+}
+
 /// A concrete implementation of a [PropertyInducingElement].
 abstract class PropertyInducingElementImpl
     extends NonParameterVariableElementImpl
     with MacroTargetElement
-    implements PropertyInducingElement, PropertyInducingFragment {
+    implements PropertyInducingElementOrMember, PropertyInducingFragment {
   @override
   String? name2;
 
@@ -10449,6 +10487,14 @@
   List<PropertyInducingElementImpl> get _fragments;
 }
 
+/// Common base class for all analyzer-internal classes that implement
+/// `PropertyInducingElement`.
+abstract class PropertyInducingElementOrMember
+    implements PropertyInducingElement, VariableElementOrMember {
+  @override
+  TypeImpl get type;
+}
+
 /// Instances of this class are set for fields and top-level variables
 /// to perform top-level type inference during linking.
 abstract class PropertyInducingElementTypeInference {
@@ -10844,7 +10890,7 @@
       firstFragment.setter2?.element as SetterElement?;
 
   @override
-  DartType get type => firstFragment.type;
+  TypeImpl get type => firstFragment.type;
 
   @override
   T? accept2<T>(ElementVisitor2<T> visitor) {
@@ -11553,9 +11599,16 @@
   }
 }
 
+/// Common base class for all analyzer-internal classes that implement
+/// `VariableElement2`.
+abstract class VariableElement2OrMember implements VariableElement2 {
+  @override
+  TypeImpl get type;
+}
+
 /// A concrete implementation of a [VariableElement].
 abstract class VariableElementImpl extends ElementImpl
-    implements VariableElement {
+    implements VariableElementOrMember {
   /// The type of this variable.
   TypeImpl? _type;
 
@@ -11665,7 +11718,7 @@
 }
 
 abstract class VariableElementImpl2 extends ElementImpl2
-    implements VariableElement2 {
+    implements VariableElement2OrMember {
   @override
   void visitChildren2<T>(ElementVisitor2<T> visitor) {
     for (var child in children2) {
@@ -11674,6 +11727,13 @@
   }
 }
 
+/// Common base class for all analyzer-internal classes that implement
+/// `VariableElement`.
+abstract class VariableElementOrMember implements VariableElement {
+  @override
+  TypeImpl get type;
+}
+
 mixin WrappedElementMixin implements ElementImpl2 {
   @override
   bool get isSynthetic => _wrappedElement.isSynthetic;
diff --git a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
index 8a37ecb..a6e223f 100644
--- a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
+++ b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
@@ -79,7 +79,7 @@
   ///
   /// If such signature does not exist, return `null`, and if [conflicts] is
   /// not `null`, add a new [Conflict] to it.
-  ExecutableElement? combineSignatures({
+  ExecutableElementOrMember? combineSignatures({
     required InterfaceElement targetClass,
     required List<ExecutableElement> candidates,
     required bool doTopMerge,
@@ -88,15 +88,20 @@
   }) {
     // If just one candidate, it is always valid.
     if (candidates.length == 1) {
-      return candidates[0];
+      // TODO(paulberry): eliminate this cast by changing the type of the
+      // parameter `candidates`.
+      return candidates[0] as ExecutableElementOrMember;
     }
 
     var targetLibrary = targetClass.library as LibraryElementImpl;
     var typeSystem = targetLibrary.typeSystem;
 
-    var validOverrides = <ExecutableElement>[];
+    var validOverrides = <ExecutableElementOrMember>[];
     for (var i = 0; i < candidates.length; i++) {
-      ExecutableElement? validOverride = candidates[i];
+      // TODO(paulberry): eliminate this cast by changing the type of the
+      // parameter `candidates`.
+      ExecutableElementOrMember? validOverride =
+          candidates[i] as ExecutableElementOrMember;
       var validOverrideType = validOverride.type;
       for (var j = 0; j < candidates.length; j++) {
         var candidate = candidates[j];
@@ -147,7 +152,8 @@
   /// at all, or because there is no the most specific signature.
   ///
   /// This is equivalent to `getInheritedMap2(type)[name]`.
-  ExecutableElement? getInherited2(InterfaceElement element, Name name) {
+  ExecutableElementOrMember? getInherited2(
+      InterfaceElement element, Name name) {
     return getInheritedMap2(element)[name];
   }
 
@@ -210,7 +216,8 @@
   /// inherited from the super-interfaces (superclasses, mixins, and
   /// interfaces).  If there is no most specific signature for a name, the
   /// corresponding name will not be included.
-  Map<Name, ExecutableElement> getInheritedMap2(InterfaceElement element) {
+  Map<Name, ExecutableElementOrMember> getInheritedMap2(
+      InterfaceElement element) {
     var interface = getInterface(element);
     var inheritedMap = interface.inheritedMap;
     if (inheritedMap == null) {
@@ -230,6 +237,9 @@
   /// Return the interface of the given [element].  It might include
   /// private members, not necessary accessible in all libraries.
   Interface getInterface(InterfaceElement element) {
+    // TODO(paulberry): eliminate this cast by changing the type of the
+    // parameter `element`.
+    element as InterfaceElementImpl;
     if (element.augmentationTarget != null) {
       throw ArgumentError('Interfaces can only be asked for declarations');
     }
@@ -245,9 +255,9 @@
     }
 
     try {
-      if (element is ExtensionTypeElement) {
+      if (element is ExtensionTypeElementImpl) {
         result = _getInterfaceExtensionType(element);
-      } else if (element is MixinElement) {
+      } else if (element is MixinElementImpl) {
         result = _getInterfaceMixin(element);
       } else {
         result = _getInterfaceClass(element);
@@ -270,7 +280,7 @@
   }
 
   /// Return the result of [getMember2] with [type] substitution.
-  ExecutableElement? getMember(
+  ExecutableElementOrMember? getMember(
     InterfaceType type,
     Name name, {
     bool concrete = false,
@@ -289,6 +299,8 @@
     }
 
     var substitution = Substitution.fromInterfaceType(type);
+    // TODO(paulberry): eliminate this cast by changing the return type of
+    // `ExecutalbeMember.from2`.
     return ExecutableMember.from2(rawElement, substitution);
   }
 
@@ -303,7 +315,7 @@
   /// If [forMixinIndex] is specified, only the nominal superclass, and the
   /// given number of mixins after it are considered.  For example for `1` in
   /// `class C extends S with M1, M2, M3`, only `S` and `M1` are considered.
-  ExecutableElement? getMember2(
+  ExecutableElementOrMember? getMember2(
     InterfaceElement element,
     Name name, {
     bool concrete = false,
@@ -559,12 +571,12 @@
     return conflicts;
   }
 
-  Interface _getInterfaceClass(InterfaceElement element) {
+  Interface _getInterfaceClass(InterfaceElementImpl element) {
     var augmented = element.augmented;
 
     var namedCandidates = <Name, List<ExecutableElement>>{};
-    var superImplemented = <Map<Name, ExecutableElement>>[];
-    var implemented = <Name, ExecutableElement>{};
+    var superImplemented = <Map<Name, ExecutableElementOrMember>>[];
+    var implemented = <Name, ExecutableElementOrMember>{};
 
     InterfaceType? superType = element.supertype;
 
@@ -697,7 +709,7 @@
     );
 
     var noSuchMethodForwarders = <Name>{};
-    if (element is ClassElement && element.isAbstract) {
+    if (element is ClassElementImpl && element.isAbstract) {
       if (superTypeInterface != null) {
         noSuchMethodForwarders = superTypeInterface.noSuchMethodForwarders;
       }
@@ -724,7 +736,8 @@
       }
     }
 
-    implemented = implemented.map<Name, ExecutableElement>((key, value) {
+    implemented =
+        implemented.map<Name, ExecutableElementOrMember>((key, value) {
       var result = _inheritCovariance(element, namedCandidates, key, value);
       return MapEntry(key, result);
     });
@@ -752,7 +765,7 @@
     var augmented = element.augmented;
 
     // Add instance members implemented by the element itself.
-    var declared = <Name, ExecutableElement>{};
+    var declared = <Name, ExecutableElementOrMember>{};
     _addImplemented(declared, element, augmented);
 
     // Prepare precluded names.
@@ -832,7 +845,7 @@
       }
 
       // The inherited member must be unique.
-      ExecutableElement? uniqueElement;
+      ExecutableElementOrMember? uniqueElement;
       for (var candidate in notPrecluded) {
         if (uniqueElement == null) {
           uniqueElement = candidate;
@@ -938,7 +951,7 @@
     );
   }
 
-  Interface _getInterfaceMixin(MixinElement element) {
+  Interface _getInterfaceMixin(MixinElementImpl element) {
     var augmented = element.augmented;
 
     var superCandidates = <Name, List<ExecutableElement>>{};
@@ -954,7 +967,7 @@
 
     // `mixin M on S1, S2 {}` can call using `super` any instance member
     // from its superclass constraints, whether it is abstract or concrete.
-    var superInterface = <Name, ExecutableElement>{};
+    var superInterface = <Name, ExecutableElementOrMember>{};
     var superConflicts = _findMostSpecificFromNamedCandidates(
       element,
       superInterface,
@@ -981,7 +994,7 @@
       doTopMerge: true,
     );
 
-    var implemented = <Name, ExecutableElement>{};
+    var implemented = <Name, ExecutableElementOrMember>{};
     _addImplemented(implemented, element, augmented);
 
     return Interface._(
@@ -1004,11 +1017,11 @@
   /// a copy of the [executable] with the corresponding parameters marked
   /// covariant. If there are no covariant parameters, or parameters to
   /// update are already covariant, return the [executable] itself.
-  ExecutableElement _inheritCovariance(
+  ExecutableElementOrMember _inheritCovariance(
     InterfaceElement class_,
     Map<Name, List<ExecutableElement>> namedCandidates,
     Name name,
-    ExecutableElement executable,
+    ExecutableElementOrMember executable,
   ) {
     if (executable.enclosingElement3 == class_) {
       return executable;
@@ -1103,10 +1116,10 @@
 
   /// Given one or more [validOverrides], merge them into a single resulting
   /// signature. This signature always exists.
-  ExecutableElement _topMerge(
+  ExecutableElementOrMember _topMerge(
     TypeSystemImpl typeSystem,
     InterfaceElement targetClass,
-    List<ExecutableElement> validOverrides,
+    List<ExecutableElementOrMember> validOverrides,
   ) {
     var first = validOverrides[0];
 
@@ -1191,11 +1204,11 @@
     }
   }
 
-  static Map<Name, ExecutableElement> _getTypeMembers(
+  static Map<Name, ExecutableElementOrMember> _getTypeMembers(
     InterfaceElement element,
-    AugmentedInterfaceElement augmented,
+    InterfaceElementImpl2 augmented,
   ) {
-    var declared = <Name, ExecutableElement>{};
+    var declared = <Name, ExecutableElementOrMember>{};
     var libraryUri = element.librarySource.uri;
 
     var methods = augmented.methods;
@@ -1240,13 +1253,13 @@
   );
 
   /// The map of names to their signature in the interface.
-  final Map<Name, ExecutableElement> map;
+  final Map<Name, ExecutableElementOrMember> map;
 
   /// The map of declared names to their signatures.
   final Map<Name, ExecutableElement> declared;
 
   /// The map of names to their concrete implementations.
-  final Map<Name, ExecutableElement> implemented;
+  final Map<Name, ExecutableElementOrMember> implemented;
 
   /// The set of names that are `noSuchMethod` forwarders in [implemented].
   final Set<Name> noSuchMethodForwarders;
@@ -1267,7 +1280,7 @@
   /// The first item of the list is the nominal superclass, next the nominal
   /// superclass plus the first mixin, etc. So, for the class like
   /// `class C extends S with M1, M2`, we get `[S, S&M1, S&M1&M2]`.
-  final List<Map<Name, ExecutableElement>> superImplemented;
+  final List<Map<Name, ExecutableElementOrMember>> superImplemented;
 
   /// The list of conflicts between superinterfaces - the nominal superclass,
   /// mixins, and interfaces.  Does not include conflicts with the declared
@@ -1276,7 +1289,7 @@
 
   /// The map of names to the most specific signatures from the mixins,
   /// superclasses, or interfaces.
-  Map<Name, ExecutableElement>? inheritedMap;
+  Map<Name, ExecutableElementOrMember>? inheritedMap;
 
   Interface._({
     required this.map,
@@ -1408,9 +1421,9 @@
 
 class _ExtensionTypeCandidates {
   final Name name;
-  final List<MethodElement> methods = [];
-  final List<PropertyAccessorElement> getters = [];
-  final List<PropertyAccessorElement> setters = [];
+  final List<MethodElementOrMember> methods = [];
+  final List<PropertyAccessorElementOrMember> getters = [];
+  final List<PropertyAccessorElementOrMember> setters = [];
 
   _ExtensionTypeCandidates(this.name);
 
@@ -1418,18 +1431,18 @@
     return [...methods, ...getters, ...setters];
   }
 
-  void add(ExecutableElement element) {
+  void add(ExecutableElementOrMember element) {
     switch (element) {
-      case MethodElement():
+      case MethodElementOrMember():
         methods.add(element);
-      case PropertyAccessorElement(isGetter: true):
+      case PropertyAccessorElementOrMember(isGetter: true):
         getters.add(element);
-      case PropertyAccessorElement(isSetter: true):
+      case PropertyAccessorElementOrMember(isSetter: true):
         setters.add(element);
     }
   }
 
-  List<ExecutableElement> notPrecluded({
+  List<ExecutableElementOrMember> notPrecluded({
     required Set<Name> precludedNames,
     required Set<Name> precludedMethods,
     required Set<Name> precludedSetters,
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index a870002..4d5fe2d 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -202,7 +202,7 @@
 /// An executable element defined in a parameterized type where the values of
 /// the type parameters are known.
 abstract class ExecutableMember extends Member
-    implements ExecutableElement, ExecutableElement2 {
+    implements ExecutableElementOrMember, ExecutableElement2 {
   @override
   final List<TypeParameterElement> typeParameters;
 
@@ -316,11 +316,13 @@
   }
 
   @override
-  DartType get returnType {
+  TypeImpl get returnType {
     var result = declaration.returnType;
     result = augmentationSubstitution.substituteType(result);
     result = _substitution.substituteType(result);
-    return result;
+    // TODO(paulberry): eliminate this cast by changing the type of
+    // `declaration`.
+    return result as TypeImpl;
   }
 
   @override
@@ -384,7 +386,7 @@
     return from2(element.asElement, substitution).asElement2;
   }
 
-  static ExecutableElement from2(
+  static ExecutableElementOrMember from2(
     ExecutableElement element,
     MapSubstitution substitution,
   ) {
@@ -405,7 +407,9 @@
     }
 
     if (augmentationSubstitution.map.isEmpty && combined.map.isEmpty) {
-      return element;
+      // TODO(paulberry): eliminate this cast by changing the type of the
+      // parameter `element`.
+      return element as ExecutableElementOrMember;
     }
 
     if (element is ConstructorElement) {
@@ -502,7 +506,11 @@
 /// A field element defined in a parameterized type where the values of the type
 /// parameters are known.
 class FieldMember extends VariableMember
-    implements FieldElement, FieldElement2 {
+    implements
+        FieldElement,
+        FieldElement2,
+        VariableElement2OrMember,
+        PropertyInducingElementOrMember {
   /// Initialize a newly created element to represent a field, based on the
   /// [declaration], with applied [substitution].
   FieldMember(
@@ -1340,7 +1348,7 @@
 /// A property accessor element defined in a parameterized type where the values
 /// of the type parameters are known.
 abstract class PropertyAccessorMember extends ExecutableMember
-    implements PropertyAccessorElement, PropertyAccessorElement2 {
+    implements PropertyAccessorElementOrMember, PropertyAccessorElement2 {
   factory PropertyAccessorMember(
     PropertyAccessorElement declaration,
     MapSubstitution augmentationSubstitution,
@@ -1405,8 +1413,8 @@
   }
 
   @override
-  PropertyAccessorElement get declaration =>
-      super.declaration as PropertyAccessorElement;
+  PropertyAccessorElementImpl get declaration =>
+      super.declaration as PropertyAccessorElementImpl;
 
   @override
   Element get enclosingElement3 => declaration.enclosingElement3;
@@ -1427,12 +1435,12 @@
   Source get source => _declaration.source!;
 
   @override
-  PropertyInducingElement? get variable2 {
+  PropertyInducingElementOrMember? get variable2 {
     // TODO(scheglov): revisit
     var variable = declaration.variable2;
-    if (variable is FieldElement) {
+    if (variable is FieldElementImpl) {
       return FieldMember(variable, augmentationSubstitution, _substitution);
-    } else if (variable is TopLevelVariableElement) {
+    } else if (variable is TopLevelVariableElementImpl) {
       return TopLevelVariableMember(
           variable, augmentationSubstitution, _substitution);
     }
@@ -1572,7 +1580,7 @@
 }
 
 class TopLevelVariableMember extends VariableMember
-    implements TopLevelVariableElement {
+    implements TopLevelVariableElement, PropertyInducingElementOrMember {
   TopLevelVariableMember(
     super.declaration,
     super.augmentationSubstitution,
@@ -1648,7 +1656,8 @@
 
 /// A variable element defined in a parameterized type where the values of the
 /// type parameters are known.
-abstract class VariableMember extends Member implements VariableElement {
+abstract class VariableMember extends Member
+    implements VariableElementOrMember {
   TypeImpl? _type;
 
   /// Initialize a newly created element to represent a variable, based on the
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 2b78232..396ccb2 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -989,7 +989,7 @@
     if (inherited) {
       if (concrete) {
         var result = inheritance.getMember(this, nameObj, forSuper: inherited);
-        if (result is PropertyAccessorElement) {
+        if (result is PropertyAccessorElementOrMember) {
           return result;
         }
       } else {
@@ -1002,7 +1002,7 @@
     }
 
     var result = inheritance.getMember(this, nameObj, concrete: concrete);
-    if (result is PropertyAccessorElement) {
+    if (result is PropertyAccessorElementOrMember) {
       return result;
     }
 
@@ -1044,7 +1044,7 @@
     if (inherited) {
       if (concrete) {
         var result = inheritance.getMember(this, nameObj, forSuper: inherited);
-        if (result is MethodElement) {
+        if (result is MethodElementOrMember) {
           return result;
         }
       } else {
@@ -1057,7 +1057,7 @@
     }
 
     var result = inheritance.getMember(this, nameObj, concrete: concrete);
-    if (result is MethodElement) {
+    if (result is MethodElementOrMember) {
       return result;
     }
 
@@ -1099,7 +1099,7 @@
     if (inherited) {
       if (concrete) {
         var result = inheritance.getMember(this, nameObj, forSuper: inherited);
-        if (result is PropertyAccessorElement) {
+        if (result is PropertyAccessorElementOrMember) {
           return result;
         }
       } else {
@@ -1112,7 +1112,7 @@
     }
 
     var result = inheritance.getMember(this, nameObj, concrete: concrete);
-    if (result is PropertyAccessorElement) {
+    if (result is PropertyAccessorElementOrMember) {
       return result;
     }
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
index 091ea9b..295c5e6 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
@@ -1214,8 +1214,8 @@
   _LocalVariableTypeProvider(this._manager);
 
   @override
-  DartType getType(SimpleIdentifierImpl node, {required bool isRead}) {
-    var variable = node.element as VariableElement2;
+  TypeImpl getType(SimpleIdentifierImpl node, {required bool isRead}) {
+    var variable = node.element as VariableElement2OrMember;
     if (variable is PromotableElementImpl2) {
       var promotedType = isRead
           ? _manager.flow?.variableRead(node, variable)
diff --git a/pkg/analyzer/lib/src/error/inheritance_override.dart b/pkg/analyzer/lib/src/error/inheritance_override.dart
index 7029f4e..ed37076 100644
--- a/pkg/analyzer/lib/src/error/inheritance_override.dart
+++ b/pkg/analyzer/lib/src/error/inheritance_override.dart
@@ -356,7 +356,7 @@
           superMember: interfaceElement,
           errorReporter: reporter,
           errorNode: classNameToken,
-          errorCode: concreteElement is PropertyAccessorElement &&
+          errorCode: concreteElement is PropertyAccessorElementOrMember &&
                   concreteElement.isSetter
               ? CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE_SETTER
               : CompileTimeErrorCode.INVALID_IMPLEMENTATION_OVERRIDE,
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index a6e3bf5..522f686 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -2471,12 +2471,12 @@
         );
       }
 
-      if (getter is PropertyAccessorElement) {
+      if (getter is PropertyAccessorElementOrMember) {
         reportFieldConflict(getter);
         continue;
       }
 
-      if (setter is PropertyAccessorElement) {
+      if (setter is PropertyAccessorElementOrMember) {
         reportFieldConflict(setter);
         continue;
       }
@@ -2503,7 +2503,7 @@
           ],
         );
         conflictingDeclaredNames.add(name);
-      } else if (inherited is MethodElement) {
+      } else if (inherited is MethodElementOrMember) {
         // Extension type accessors preclude inherited accessors/methods.
         if (enclosingClass is ExtensionTypeElement) {
           continue;
@@ -2532,7 +2532,7 @@
         }
         var setterName = methodName.forSetter;
         var setter = inherited[setterName];
-        if (setter is PropertyAccessorElement) {
+        if (setter is PropertyAccessorElementOrMember) {
           errorReporter.atElement(
             enclosingClass,
             CompileTimeErrorCode.CONFLICTING_INHERITED_METHOD_AND_SETTER,
diff --git a/pkg/analyzer/lib/src/summary2/instance_member_inferrer.dart b/pkg/analyzer/lib/src/summary2/instance_member_inferrer.dart
index c25db87..5b19944 100644
--- a/pkg/analyzer/lib/src/summary2/instance_member_inferrer.dart
+++ b/pkg/analyzer/lib/src/summary2/instance_member_inferrer.dart
@@ -135,9 +135,7 @@
         name: getterName,
       );
       if (combinedGetter != null) {
-        // TODO(paulberry): eliminate this cast by changing the return type of
-        // `InheritanceManager3.combineSignatures`.
-        return combinedGetter.returnType as TypeImpl;
+        return combinedGetter.returnType;
       }
       return DynamicTypeImpl.instance;
     }