Index: pkg/analyzer/lib/src/task/strong/checker.dart |
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart |
index ec01b5e006400c4449d141dc644bb5d46a5257af..568a59856d7493306e0db16ce98b1e570b9bb27a 100644 |
--- a/pkg/analyzer/lib/src/task/strong/checker.dart |
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart |
@@ -1637,7 +1637,10 @@ class _OverrideChecker { |
// |
// Because of that, it is important we visit types in the order that they |
// will override members. |
- void checkType(InterfaceType type, AstNode location) { |
+ // If checkingMixin is true, then we are checking [type] in a mixin position |
+ // and hence should consider its own mixins and superclass as abstract. |
+ void checkType(InterfaceType type, AstNode location, |
+ {bool checkingMixin: false}) { |
// Skip `Object` because we don't need to check those members here. |
// (because `Object` is the root of everything, it will be checked in |
// _checkSuperOverrides for all classes). |
@@ -1669,18 +1672,31 @@ class _OverrideChecker { |
_checkTypeMembers(type, checkOverride); |
} |
- // Check mixin members against interfaces. |
- // |
- // We visit mixins in reverse order to reflect how they override |
- // eachother. |
- for (int i = type.mixins.length - 1; i >= 0; i--) { |
- checkType(type.mixins[i], |
- isRootClass ? _withClause(node).mixinTypes[i] : location); |
- } |
+ // If we are currently checking a mixin, then its own mixins and |
+ // superclass are abstract, and we should not check their members. |
+ // This should only happen when super mixins is enabled, and we |
+ // don't do proper checking for super mixins (we don't check that |
+ // the contract implied by the mixin declaration is satisfied by |
+ // the mixin use), but this prevents us from erroneously |
+ // rejecting some super mixin patterns. |
+ // If this is a mixin application (class A = Object with B) |
+ // however, then we do still need to treat the mixin as concrete. |
+ if (!checkingMixin || type.element.isMixinApplication) { |
+ // Check mixin members against interfaces. |
+ // |
+ // We visit mixins in reverse order to reflect how they override |
+ // eachother. |
+ for (int i = type.mixins.length - 1; i >= 0; i--) { |
+ checkType(type.mixins[i], |
+ isRootClass ? _withClause(node).mixinTypes[i] : location, |
+ checkingMixin: true); |
+ } |
- // Check members on the superclass. |
- checkType(type.superclass, |
- isRootClass ? _extendsErrorLocation(node) : location); |
+ // Check members on the superclass. |
+ checkType(type.superclass, |
+ isRootClass ? _extendsErrorLocation(node) : location, |
+ checkingMixin: checkingMixin); |
+ } |
} |
checkType(element.type, node); |