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 {}