Elements. Track not yet inferred classes in a set in InstanceMemberInferrer instead of a field in InterfaceElementImpl.

Change-Id: I3cf6962813d1e62e7b0caaa5e0a2cd9601e26781
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/448243
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: 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 dc5f033..8ed4b8b4 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -4629,10 +4629,6 @@
   List<InterfaceTypeImpl>? Function(InterfaceElementImpl)?
   mixinInferenceCallback;
 
-  /// A flag indicating whether the types associated with the instance members
-  /// of this class have been inferred.
-  bool hasBeenInferred = false;
-
   /// Whether the class or its superclass declares a non-final instance field.
   bool hasNonFinalField = false;
 
diff --git a/pkg/analyzer/lib/src/summary2/instance_member_inferrer.dart b/pkg/analyzer/lib/src/summary2/instance_member_inferrer.dart
index f9f2bf4..343fece 100644
--- a/pkg/analyzer/lib/src/summary2/instance_member_inferrer.dart
+++ b/pkg/analyzer/lib/src/summary2/instance_member_inferrer.dart
@@ -18,7 +18,7 @@
 /// https://github.com/dart-lang/language/blob/main/resources/type-system/inference.md
 class InstanceMemberInferrer {
   final InheritanceManager3 inheritance;
-  final Set<InterfaceElementImpl> elementsBeingInferred = {};
+  final Set<InterfaceElementImpl> interfacesToInfer = {};
 
   late InterfaceElementImpl currentInterfaceElement;
 
@@ -29,11 +29,11 @@
     return currentInterfaceElement.library.typeSystem;
   }
 
-  void inferLibrary(LibraryElementImpl library) {
-    _inferClasses(library.classes);
-    _inferClasses(library.enums);
-    _inferExtensionTypes(library.extensionTypes);
-    _inferClasses(library.mixins);
+  void perform(List<InterfaceElementImpl> elements) {
+    interfacesToInfer.addAll(elements);
+    for (var element in elements) {
+      _inferClass(element);
+    }
   }
 
   /// Return `true` if the elements corresponding to the [elements] have the
@@ -317,67 +317,43 @@
   /// Infer type information for all of the instance members in the given
   /// [element].
   void _inferClass(InterfaceElementImpl element) {
-    if (element.hasBeenInferred) {
+    if (!interfacesToInfer.remove(element)) {
       return;
     }
 
     _setInducedModifier(element);
 
-    if (!elementsBeingInferred.add(element)) {
-      // We have found a circularity in the class hierarchy. For now we just
-      // stop trying to infer any type information for any classes that
-      // inherit from any class in the cycle. We could potentially limit the
-      // algorithm to only not inferring types in the classes in the cycle,
-      // but it isn't clear that the results would be significantly better.
-      throw _CycleException();
+    //
+    // Ensure that all of instance members in the supertypes have had types
+    // inferred for them.
+    //
+    _inferType(element.supertype);
+    element.mixins.forEach(_inferType);
+    element.interfaces.forEach(_inferType);
+
+    //
+    // Then infer the types for the members.
+    //
+    currentInterfaceElement = element;
+    for (var field in element.fields) {
+      _inferAccessorOrField(field: field);
+    }
+    for (var getter in element.getters) {
+      _inferAccessorOrField(getter: getter);
+    }
+    for (var setter in element.setters) {
+      _inferAccessorOrField(setter: setter);
+    }
+    for (var method in element.methods) {
+      _inferExecutable(method);
     }
 
-    try {
-      //
-      // Ensure that all of instance members in the supertypes have had types
-      // inferred for them.
-      //
-      _inferType(element.supertype);
-      element.mixins.forEach(_inferType);
-      element.interfaces.forEach(_inferType);
-      //
-      // Then infer the types for the members.
-      //
-      // TODO(scheglov): get other members from the container
-      currentInterfaceElement = element;
-      for (var field in element.fields) {
-        _inferAccessorOrField(field: field);
-      }
-      for (var getter in element.getters) {
-        _inferAccessorOrField(getter: getter);
-      }
-      for (var setter in element.setters) {
-        _inferAccessorOrField(setter: setter);
-      }
-      for (var method in element.methods) {
-        _inferExecutable(method);
-      }
-      //
-      // Infer initializing formal parameter types. This must happen after
-      // field types are inferred.
-      //
-      for (var constructor in element.constructors) {
-        _inferConstructor(constructor);
-      }
-      element.hasBeenInferred = true;
-    } finally {
-      elementsBeingInferred.remove(element);
-    }
-  }
-
-  void _inferClasses(List<InterfaceElementImpl> elements) {
-    for (var element in elements) {
-      try {
-        _inferClass(element);
-      } on _CycleException {
-        // This is a short circuit return to prevent types that inherit from
-        // types containing a circular reference from being inferred.
-      }
+    //
+    // Infer initializing formal parameter types. This must happen after
+    // field types are inferred.
+    //
+    for (var constructor in element.constructors) {
+      _inferConstructor(constructor);
     }
   }
 
@@ -494,14 +470,6 @@
     _resetOperatorEqualParameterTypeToDynamic(element, overriddenElements);
   }
 
-  void _inferExtensionTypes(List<ExtensionTypeElementImpl> extensionTypes) {
-    for (var extensionType in extensionTypes) {
-      for (var constructor in extensionType.constructors) {
-        _inferConstructor(constructor);
-      }
-    }
-  }
-
   void _inferMixinApplicationConstructor(
     ClassElementImpl classElement,
     ConstructorElementImpl constructor,
@@ -757,9 +725,6 @@
   }
 }
 
-/// A class of exception that is not used anywhere else.
-class _CycleException implements Exception {}
-
 extension on InterfaceElementImpl {
   bool get isBase {
     switch (this) {
diff --git a/pkg/analyzer/lib/src/summary2/top_level_inference.dart b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
index 0ea15f0..7417d75 100644
--- a/pkg/analyzer/lib/src/summary2/top_level_inference.dart
+++ b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
@@ -98,10 +98,12 @@
   }
 
   void _performOverrideInference() {
+    var interfacesToInfer = linker.builders.values.expand((builder) {
+      return builder.element.children.whereType<InterfaceElementImpl>();
+    }).toList();
+
     var inferrer = InstanceMemberInferrer(linker.inheritance);
-    for (var builder in linker.builders.values) {
-      inferrer.inferLibrary(builder.element);
-    }
+    inferrer.perform(interfacesToInfer);
   }
 }