Test for mixin declaration isObject and tweaks for error verifier.

R=brianwilkerson@google.com

Change-Id: I902dfdaf5e39c457e2ff365dfdd6b8f4d830497f
Reviewed-on: https://dart-review.googlesource.com/75381
Reviewed-by: Brian Wilkerson <brianwilkerson@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 4e466b6..627ce03 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -6697,6 +6697,14 @@
   }
 
   @override
+  InterfaceType get supertype => null;
+
+  @override
+  void set supertype(InterfaceType supertype) {
+    throw new StateError('Attempt to set a supertype for a mixin declaratio.');
+  }
+
+  @override
   void appendTo(StringBuffer buffer) {
     buffer.write('mixin ');
     String name = displayName;
@@ -8698,23 +8706,6 @@
   List<UnlinkedTypeParam> get unlinkedTypeParams;
 
   /**
-   * Convert the given [index] into a type parameter type.
-   */
-  TypeParameterType getTypeParameterType(int index) {
-    List<TypeParameterType> types = typeParameterTypes;
-    if (index <= types.length) {
-      return types[types.length - index];
-    } else if (enclosingTypeParameterContext != null) {
-      return enclosingTypeParameterContext
-          .getTypeParameterType(index - types.length);
-    } else {
-      // If we get here, it means that a summary contained a type parameter index
-      // that was out of range.
-      throw new RangeError('Invalid type parameter index');
-    }
-  }
-
-  /**
    * Return the given [typeParameter]'s de Bruijn index in this context, or
    * `null` if it's not in scope.
    *
@@ -8733,6 +8724,23 @@
       return null;
     }
   }
+
+  /**
+   * Convert the given [index] into a type parameter type.
+   */
+  TypeParameterType getTypeParameterType(int index) {
+    List<TypeParameterType> types = typeParameterTypes;
+    if (index <= types.length) {
+      return types[types.length - index];
+    } else if (enclosingTypeParameterContext != null) {
+      return enclosingTypeParameterContext
+          .getTypeParameterType(index - types.length);
+    } else {
+      // If we get here, it means that a summary contained a type parameter index
+      // that was out of range.
+      throw new RangeError('Invalid type parameter index');
+    }
+  }
 }
 
 /**
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 9a7f698..a38db59 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -1910,9 +1910,8 @@
       return false;
     }
     bool problemReported = false;
-    List<TypeName> mixinTypes = withClause.mixinTypes;
-    for (int i = 0; i < mixinTypes.length; i++) {
-      TypeName mixinName = mixinTypes[i];
+    for (int i = 0; i < withClause.mixinTypes.length; i++) {
+      TypeName mixinName = withClause.mixinTypes[i];
       DartType mixinType = mixinName.type;
       if (mixinType is InterfaceType) {
         if (_checkForExtendsOrImplementsDisallowedClass(
@@ -1925,8 +1924,7 @@
             problemReported = true;
           }
           if (mixinElement.isMixin) {
-            if (_checkForMixinSuperclassConstraints(
-                mixinName, mixinTypes.take(i))) {
+            if (_checkForMixinSuperclassConstraints(mixinName, i)) {
               problemReported = true;
             }
             if (_checkForMixinSuperInvokedMembers(mixinName, mixinElement)) {
@@ -4258,15 +4256,21 @@
     return false;
   }
 
-  /// Check that superclass constrains for the mixin type of [mixinName]
-  /// are satisfied by the superclass and/or any previous mixin applications.
-  bool _checkForMixinSuperclassConstraints(
-      TypeName mixinName, Iterable<TypeName> previousMixins) {
-    List<InterfaceType> supertypes = [_enclosingClass.supertype];
-    supertypes.addAll(previousMixins.map((t) => t.type));
+  /// Check that superclass constrains for the mixin type of [mixinName] at
+  /// the [index] position in the mixins list are satisfied by the
+  /// [_enclosingClass], or a previous mixin.
+  bool _checkForMixinSuperclassConstraints(TypeName mixinName, int index) {
     InterfaceType mixinType = mixinName.type;
     for (var constraint in mixinType.superclassConstraints) {
-      if (!supertypes.any((s) => _typeSystem.isSubtypeOf(s, constraint))) {
+      bool isSatisfied =
+          _typeSystem.isSubtypeOf(_enclosingClass.supertype, constraint);
+      if (!isSatisfied) {
+        for (int i = 0; i < index && !isSatisfied; i++) {
+          isSatisfied =
+              _typeSystem.isSubtypeOf(_enclosingClass.mixins[i], constraint);
+        }
+      }
+      if (!isSatisfied) {
         _errorReporter.reportErrorForNode(
             CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE,
             mixinName.name,
diff --git a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
index fd872fc..c06d210 100644
--- a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
@@ -163,7 +163,12 @@
     assertElement(mixin, element);
 
     expect(element.typeParameters, isEmpty);
+
+    expect(element.supertype, isNull);
+    expect(element.type.isObject, isFalse);
+
     assertElementTypes(element.superclassConstraints, [objectType]);
+    assertElementTypes(element.interfaces, []);
   }
 
   test_element_allSupertypes() async {
@@ -929,15 +934,37 @@
     ]);
   }
 
+  test_error_mixinApplicationNoConcreteSuperInvokedMember_OK_inPreviousMixin() async {
+    addTestFile(r'''
+abstract class A {
+  void foo();
+}
+
+mixin M1 {
+  void foo() {}
+}
+
+mixin M2 on A {
+  void bar() {
+    super.foo();
+  }
+}
+
+class X extends A with M1, M2 {}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+  }
+
   test_error_mixinApplicationNoConcreteSuperInvokedMember_OK_notInvoked() async {
     addTestFile(r'''
-class A {
-  void foo() {}
+abstract class A {
+  void foo();
 }
 
 mixin M on A {}
 
-class X extends A with M {}
+abstract class X extends A with M {}
 ''');
     await resolveTestFile();
     assertNoTestErrors();
@@ -1027,6 +1054,20 @@
     assertNoTestErrors();
   }
 
+  test_error_mixinApplicationNotImplementedInterface_OK_previousMixin() async {
+    addTestFile(r'''
+class A {}
+
+mixin M1 implements A {}
+
+mixin M2 on A {}
+
+class X = Object with M1, M2;
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+  }
+
   test_error_mixinApplicationNotImplementedInterface_oneOfTwo() async {
     addTestFile(r'''
 class A {}