Fix checks for absence of concrete implementations of super-invoked members.

R=brianwilkerson@google.com

Bug: https://github.com/dart-lang/sdk/issues/34113
Change-Id: Iad8ce7f2b7787a5c9640df617d99129032f8eee4
Reviewed-on: https://dart-review.googlesource.com/75783
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index b8a110c..5e4e7bd 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -1761,11 +1761,13 @@
   }
 
   ExecutableElement lookUpInheritedMember(String name, LibraryElement library,
-      {bool concrete: false, bool setter: false}) {
+      {bool concrete: false, int stopMixinIndex, bool setter: false}) {
     HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
 
     ExecutableElement lookUpImpl(InterfaceTypeImpl type,
-        {bool acceptAbstract: false, bool includeType: true}) {
+        {bool acceptAbstract: false,
+        bool includeType: true,
+        int stopMixinIndex}) {
       if (type == null || !visitedClasses.add(type.element)) {
         return null;
       }
@@ -1789,8 +1791,12 @@
         }
       }
 
-      for (InterfaceType mixin in type.mixins.reversed) {
-        var result = lookUpImpl(mixin, acceptAbstract: acceptAbstract);
+      var mixins = type.mixins;
+      for (var i = 0; i < mixins.length; i++) {
+        if (stopMixinIndex != null && i >= stopMixinIndex) {
+          break;
+        }
+        var result = lookUpImpl(mixins[i], acceptAbstract: acceptAbstract);
         if (result != null) {
           return result;
         }
@@ -1819,7 +1825,11 @@
       }
       return null;
     } else {
-      return lookUpImpl(this, includeType: false);
+      return lookUpImpl(
+        this,
+        includeType: false,
+        stopMixinIndex: stopMixinIndex,
+      );
     }
   }
 
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 41b7cbe..8c767a0 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -1926,7 +1926,7 @@
             if (_checkForMixinSuperclassConstraints(mixinName, i)) {
               problemReported = true;
             }
-            if (_checkForMixinSuperInvokedMembers(mixinName, mixinElement)) {
+            if (_checkForMixinSuperInvokedMembers(i, mixinName, mixinElement)) {
               problemReported = true;
             }
           } else {
@@ -4268,15 +4268,18 @@
     return false;
   }
 
-  /// Check that the [_enclosingClass] has concrete implementations of all
-  /// the super-invoked members of the [mixinElement].
+  /// Check that the superclass of the given [mixinElement] at the given
+  /// [mixinIndex] in the list of mixins of [_enclosingClass] has concrete
+  /// implementations of all the super-invoked members of the [mixinElement].
   bool _checkForMixinSuperInvokedMembers(
-      TypeName mixinName, ClassElementImpl mixinElement) {
+      int mixinIndex, TypeName mixinName, ClassElementImpl mixinElement) {
     InterfaceTypeImpl enclosingType = _enclosingClass.type;
     for (var name in mixinElement.superInvokedNames) {
       var superMember = enclosingType.lookUpInheritedMember(
           name, _currentLibrary,
-          concrete: true, setter: name.endsWith('='));
+          concrete: true,
+          stopMixinIndex: mixinIndex,
+          setter: name.endsWith('='));
       if (superMember == null) {
         _errorReporter.reportErrorForNode(
             CompileTimeErrorCode
diff --git a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
index 674f182..0375fc2 100644
--- a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
@@ -918,6 +918,50 @@
     ]);
   }
 
+  test_error_mixinApplicationNoConcreteSuperInvokedMember_inNextMixin() async {
+    addTestFile('''
+abstract class A {
+  void foo();
+}
+
+mixin M1 on A {
+  void foo() {
+    super.foo();
+  }
+}
+
+mixin M2 on A {
+  void foo() {}
+}
+
+class X extends A with M1, M2 {}
+''');
+    await resolveTestFile();
+    assertTestErrors([
+      CompileTimeErrorCode.MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER
+    ]);
+  }
+
+  test_error_mixinApplicationNoConcreteSuperInvokedMember_inSameMixin() async {
+    addTestFile('''
+abstract class A {
+  void foo();
+}
+
+mixin M on A {
+  void foo() {
+    super.foo();
+  }
+}
+
+class X extends A with M {}
+''');
+    await resolveTestFile();
+    assertTestErrors([
+      CompileTimeErrorCode.MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER
+    ]);
+  }
+
   test_error_mixinApplicationNoConcreteSuperInvokedMember_method() async {
     addTestFile(r'''
 abstract class A {
@@ -960,6 +1004,30 @@
     assertNoTestErrors();
   }
 
+  test_error_mixinApplicationNoConcreteSuperInvokedMember_OK_inSuper_fromMixin() async {
+    addTestFile(r'''
+abstract class A {
+  void foo();
+}
+
+mixin M1 {
+  void foo() {}
+}
+
+class B extends A with M1 {}
+
+mixin M2 on A {
+  void bar() {
+    super.foo();
+  }
+}
+
+class X extends B with M2 {}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+  }
+
   test_error_mixinApplicationNoConcreteSuperInvokedMember_OK_notInvoked() async {
     addTestFile(r'''
 abstract class A {