Check that the concrete member in the class has same type as the super-invoked member in the mixin.

R=brianwilkerson@google.com

Change-Id: I985872d2eb5eaf7608b030b9803d664ad0878b04
Reviewed-on: https://dart-review.googlesource.com/75243
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 17ae919..5759b93 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -175,6 +175,7 @@
   CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL,
   CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL,
   CompileTimeErrorCode.MISSING_DART_LIBRARY,
+  CompileTimeErrorCode.MIXIN_APPLICATION_CONCRETE_SUPER_INVOKED_MEMBER_TYPE,
   CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE,
   CompileTimeErrorCode.MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER,
   CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR,
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 4295352..fc72f2b 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -93,7 +93,7 @@
   /**
    * The version of data format, should be incremented on every format change.
    */
-  static const int DATA_VERSION = 67;
+  static const int DATA_VERSION = 69;
 
   /**
    * The number of exception contexts allowed to write. Once this field is
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index f4ff42b..a572b6a 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -1623,6 +1623,28 @@
           correction: "Check your Dart SDK installation for completeness.");
 
   /**
+   * It's a compile-time error to apply a mixin containing super-invocations to
+   * a class that doesn't have a concrete implementation of the super-invoked
+   * members compatible with the super-constraint interface.
+   *
+   * This ensures that if more than one super-constraint interface declares a
+   * member with the same name, at least one of those members is more specific
+   * than the rest, and this is the unique signature that super-invocations
+   * are allowed to invoke.
+   *
+   * Parameters:
+   * 0: the name of the super-invoked member
+   * 1: the display name of the type of the super-invoked member in the mixin
+   * 2: the display name of the type of the concrete member in the class
+   */
+  static const CompileTimeErrorCode
+      MIXIN_APPLICATION_CONCRETE_SUPER_INVOKED_MEMBER_TYPE =
+      const CompileTimeErrorCode(
+          'MIXIN_APPLICATION_CONCRETE_SUPER_INVOKED_MEMBER_TYPE',
+          "The super-invoked member '{0}' has the type '{1}', but the "
+          "concrete member in the class has type '{2}'.");
+
+  /**
    * It's a compile-time error to apply a mixin to a class that doesn't
    * implement all the on type requirements of the mixin declaration.
    *
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 1ebf375..9a7f698 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -4281,10 +4281,12 @@
   /// the super-invoked members of the [mixinElement].
   bool _checkForMixinSuperInvokedMembers(
       TypeName mixinName, ClassElementImpl mixinElement) {
+    InterfaceTypeImpl enclosingType = _enclosingClass.type;
     for (var name in mixinElement.superInvokedNames) {
-      if (_enclosingClass.lookUpInheritedConcreteMember(
-              name, _currentLibrary) ==
-          null) {
+      var superMember = enclosingType.lookUpInheritedMember(
+          name, _currentLibrary,
+          concrete: true, setter: name.endsWith('='));
+      if (superMember == null) {
         _errorReporter.reportErrorForNode(
             CompileTimeErrorCode
                 .MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER,
@@ -4292,6 +4294,20 @@
             [name]);
         return true;
       }
+
+      var mixinMember =
+          _inheritanceManager.lookupInheritance(mixinElement, name);
+      var superMemberType = superMember.type;
+      var mixinMemberType = mixinMember?.type;
+      if (mixinMemberType != null &&
+          !_typeSystem.isSubtypeOf(superMemberType, mixinMemberType)) {
+        _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode
+                .MIXIN_APPLICATION_CONCRETE_SUPER_INVOKED_MEMBER_TYPE,
+            mixinName.name,
+            [name, mixinMemberType.displayName, superMemberType.displayName]);
+        return true;
+      }
     }
     return false;
   }
diff --git a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
index f0bbf845..fd872fc 100644
--- a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
@@ -861,6 +861,34 @@
     assertTestErrors([CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME]);
   }
 
+  test_error_mixinApplicationConcreteSuperInvokedMemberType_method() async {
+    addTestFile(r'''
+class I {
+  void foo([int p]) {}
+}
+
+class A {
+  void foo(int p) {}
+}
+
+abstract class B extends A implements I {
+  void foo([int p]);
+}
+
+mixin M on I {
+  void bar() {
+    super.foo(42);
+  }
+}
+
+abstract class X extends B with M {}
+''');
+    await resolveTestFile();
+    assertTestErrors([
+      CompileTimeErrorCode.MIXIN_APPLICATION_CONCRETE_SUPER_INVOKED_MEMBER_TYPE,
+    ]);
+  }
+
   test_error_mixinApplicationNoConcreteSuperInvokedMember_getter() async {
     addTestFile(r'''
 abstract class A {
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index de2813b..97bbdb3 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -72,9 +72,7 @@
 issue31596_tearoff_test: CompileTimeError # Issue #31596
 issue31596_test: CompileTimeError # Issue #31596
 malformed2_test: Pass, MissingCompileTimeError # Flaky: issue 31056.
-mixin_declaration/mixin_declaration_invalid_superinvocation_test/10: CompileTimeError # bug in analyzer? Exchange UnaryNum, UnaryOptionalNum, and it works.
-mixin_declaration/mixin_declaration_superinvocation_application_test/05: MissingCompileTimeError
-mixin_declaration/mixin_declaration_supertype_compatible_test/04: MissingCompileTimeError # no most specific signature
+mixin_declaration/mixin_declaration_invalid_superinvocation_test/10: CompileTimeError # Issue 30552
 mixin_forwarding_constructor4_test/01: CompileTimeError # See issue #34375
 mixin_forwarding_constructor4_test/02: CompileTimeError # See issue #34375
 mixin_forwarding_constructor4_test/03: CompileTimeError # See issue #34375
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index 0c59d4e..21a626b 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -105,8 +105,6 @@
 label_test: RuntimeError
 left_shift_test: RuntimeError # Ints and doubles are unified.
 mixin_declaration/mixin_declaration_invalid_superinvocation_test/10: CompileTimeError    # Analyzer chooses wrong(?) super method.
-mixin_declaration/mixin_declaration_superinvocation_application_test/05: MissingCompileTimeError
-mixin_declaration/mixin_declaration_supertype_compatible_test/04: MissingCompileTimeError
 mixin_forwarding_constructor4_test/01: CompileTimeError # See issue 15101
 mixin_forwarding_constructor4_test/02: CompileTimeError # See issue 15101
 mixin_forwarding_constructor4_test/03: CompileTimeError # See issue 15101
diff --git a/tests/language_2/mixin_declaration/mixin_declaration_supertype_compatible_test.dart b/tests/language_2/mixin_declaration/mixin_declaration_supertype_compatible_test.dart
index 00bae61..5307979 100644
--- a/tests/language_2/mixin_declaration/mixin_declaration_supertype_compatible_test.dart
+++ b/tests/language_2/mixin_declaration/mixin_declaration_supertype_compatible_test.dart
@@ -11,7 +11,7 @@
 }
 
 abstract class BinaryIntNum {
-  num foo(num x, int y);
+  num foo(int x, num y);
 }
 
 abstract class GetterNumNum {