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 {