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 {