Start reporting errors for mixin super-class constraints and implements clauses.

R=brianwilkerson@google.com, paulberry@google.com

Change-Id: I6e6e3edc16737b1d3f665982f7560b46d8b71f01
Reviewed-on: https://dart-review.googlesource.com/72522
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 4422437..17387f6 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -130,7 +130,6 @@
   CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
   CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS,
   CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
-  CompileTimeErrorCode.EXTENDS_ENUM,
   CompileTimeErrorCode.EXTENDS_NON_CLASS,
   CompileTimeErrorCode.EXTERNAL_CONSTRUCTOR_WITH_FIELD_INITIALIZERS,
   CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS,
@@ -150,8 +149,6 @@
   CompileTimeErrorCode.ILLEGAL_MIXIN,
   CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS,
   CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS,
-  CompileTimeErrorCode.IMPLEMENTS_DYNAMIC,
-  CompileTimeErrorCode.IMPLEMENTS_ENUM,
   CompileTimeErrorCode.IMPLEMENTS_NON_CLASS,
   CompileTimeErrorCode.IMPLEMENTS_REPEATED,
   CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS,
@@ -203,9 +200,11 @@
   CompileTimeErrorCode.MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION,
   CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT,
   CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS,
-  CompileTimeErrorCode.MIXIN_OF_ENUM,
   CompileTimeErrorCode.MIXIN_OF_NON_CLASS,
   CompileTimeErrorCode.MIXIN_REFERENCES_SUPER,
+  CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DEFERRED_CLASS,
+  CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS,
+  CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_CLASS,
   CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS,
   CompileTimeErrorCode.MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS,
   CompileTimeErrorCode.MULTIPLE_SUPER_INITIALIZERS,
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 9fc3e5f..15245a4 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -6613,16 +6613,19 @@
   List<InterfaceType> get superclassConstraints {
     if (_superclassConstraints == null) {
       if (_unlinkedClass != null) {
+        List<InterfaceType> constraints;
         if (_unlinkedClass.superclassConstraints.isNotEmpty) {
           ResynthesizerContext context = enclosingUnit.resynthesizerContext;
-          _superclassConstraints = _unlinkedClass.superclassConstraints
+          constraints = _unlinkedClass.superclassConstraints
               .map((EntityRef t) => context.resolveTypeRef(this, t))
               .where(_isClassInterfaceType)
               .cast<InterfaceType>()
               .toList(growable: false);
-        } else {
-          _superclassConstraints = [context.typeProvider.objectType];
         }
+        if (constraints == null || constraints.isEmpty) {
+          constraints = [context.typeProvider.objectType];
+        }
+        _superclassConstraints = constraints;
       }
     }
     return _superclassConstraints ?? const <InterfaceType>[];
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index eea7df0..7663cc3 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -944,15 +944,6 @@
           correction: "Try exporting the library that the part is a part of.");
 
   /**
-   * Enum proposal: It is a compile-time error to subclass, mix-in or implement
-   * an enum.
-   */
-  static const CompileTimeErrorCode EXTENDS_ENUM = const CompileTimeErrorCode(
-      'EXTENDS_ENUM', "Classes can't extend an enum.",
-      correction:
-          "Try specifying a different superclass, or removing the extends clause.");
-
-  /**
    * 7.9 Superclasses: It is a compile-time error if the extends clause of a
    * class <i>C</i> includes a type expression that does not denote a class
    * available in the lexical scope of <i>C</i>.
@@ -1009,8 +1000,8 @@
    * See [IMPLEMENTS_DEFERRED_CLASS], and [MIXIN_DEFERRED_CLASS].
    */
   static const CompileTimeErrorCode EXTENDS_DEFERRED_CLASS =
-      const CompileTimeErrorCode('EXTENDS_DEFERRED_CLASS',
-          "This class can't extend the deferred class '{0}'.",
+      const CompileTimeErrorCode(
+          'EXTENDS_DEFERRED_CLASS', "Classes can't extend deferred classes.",
           correction: "Try specifying a different superclass, or "
               "removing the extends clause.");
 
@@ -1169,14 +1160,11 @@
    * of a class <i>C</i> specifies a malformed type or deferred type as a
    * superinterface.
    *
-   * Parameters:
-   * 0: the name of the type that is deferred
-   *
    * See [EXTENDS_DEFERRED_CLASS], and [MIXIN_DEFERRED_CLASS].
    */
   static const CompileTimeErrorCode IMPLEMENTS_DEFERRED_CLASS =
       const CompileTimeErrorCode('IMPLEMENTS_DEFERRED_CLASS',
-          "This class can't implement the deferred class '{0}'.",
+          "Classes and mixins can't implement deferred classes.",
           correction: "Try specifying a different interface, "
               "removing the class from the list, or "
               "changing the import to not be deferred.");
@@ -1207,33 +1195,13 @@
    * See [EXTENDS_DISALLOWED_CLASS].
    */
   static const CompileTimeErrorCode IMPLEMENTS_DISALLOWED_CLASS =
-      const CompileTimeErrorCode(
-          'IMPLEMENTS_DISALLOWED_CLASS', "Classes can't implement '{0}'.",
+      const CompileTimeErrorCode('IMPLEMENTS_DISALLOWED_CLASS',
+          "Classes and mixins can't implement '{0}'.",
           correction: "Try specifying a different interface, or "
               "remove the class from the list.");
 
   /**
    * 7.10 Superinterfaces: It is a compile-time error if the implements clause
-   * of a class includes type dynamic.
-   */
-  static const CompileTimeErrorCode IMPLEMENTS_DYNAMIC =
-      const CompileTimeErrorCode(
-          'IMPLEMENTS_DYNAMIC', "Classes can't implement 'dynamic'.",
-          correction:
-              "Try specifying an interface, or remove 'dynamic' from the list.");
-
-  /**
-   * Enum proposal: It is a compile-time error to subclass, mix-in or implement
-   * an enum.
-   */
-  static const CompileTimeErrorCode IMPLEMENTS_ENUM =
-      const CompileTimeErrorCode(
-          'IMPLEMENTS_ENUM', "Classes can't implement an enum.",
-          correction:
-              "Try specifying an interface, or remove the enum from the list.");
-
-  /**
-   * 7.10 Superinterfaces: It is a compile-time error if the implements clause
    * of a class <i>C</i> includes a type expression that does not denote a class
    * available in the lexical scope of <i>C</i>.
    *
@@ -1241,8 +1209,8 @@
    * 0: the name of the interface that was not found
    */
   static const CompileTimeErrorCode IMPLEMENTS_NON_CLASS =
-      const CompileTimeErrorCode(
-          'IMPLEMENTS_NON_CLASS', "Classes can only implement other classes.",
+      const CompileTimeErrorCode('IMPLEMENTS_NON_CLASS',
+          "Classes and mixins can only implement classes.",
           correction:
               "Try specifying a class, or remove the name from the list.");
 
@@ -1718,8 +1686,8 @@
    * See [EXTENDS_DEFERRED_CLASS], and [IMPLEMENTS_DEFERRED_CLASS].
    */
   static const CompileTimeErrorCode MIXIN_DEFERRED_CLASS =
-      const CompileTimeErrorCode('MIXIN_DEFERRED_CLASS',
-          "This class can't mixin the deferred class '{0}'.",
+      const CompileTimeErrorCode(
+          'MIXIN_DEFERRED_CLASS', "Classes can't mixin deferred classes.",
           correction: "Try changing the import to not be deferred.");
 
   /**
@@ -1799,13 +1767,6 @@
           'MIXIN_OF_DISALLOWED_CLASS', "Classes can't mixin '{0}'.");
 
   /**
-   * Enum proposal: It is a compile-time error to subclass, mix-in or implement
-   * an enum.
-   */
-  static const CompileTimeErrorCode MIXIN_OF_ENUM = const CompileTimeErrorCode(
-      'MIXIN_OF_ENUM', "Classes can't mixin an enum.");
-
-  /**
    * 9.1 Mixin Application: It is a compile-time error if <i>M</i> does not
    * denote a class or mixin available in the immediately enclosing scope.
    */
@@ -1823,6 +1784,22 @@
           "The class '{0}' can't be used as a mixin because it references "
           "'super'.");
 
+  static const CompileTimeErrorCode
+      MIXIN_SUPER_CLASS_CONSTRAINT_DEFERRED_CLASS = const CompileTimeErrorCode(
+          'MIXIN_SUPER_CLASS_CONSTRAINT_DEFERRED_CLASS',
+          "Deferred classes can't be used as super-class constraints.",
+          correction: "Try changing the import to not be deferred.");
+
+  static const CompileTimeErrorCode
+      MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS =
+      const CompileTimeErrorCode(
+          'MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS',
+          "'{0}' can't be used as a super-class constraint.");
+
+  static const CompileTimeErrorCode MIXIN_SUPER_CLASS_CONSTRAINT_NON_CLASS =
+      const CompileTimeErrorCode('MIXIN_SUPER_CLASS_CONSTRAINT_NON_CLASS',
+          "Only classes can be used as super-class constraints.");
+
   /**
    * 9.1 Mixin Application: It is a compile-time error if <i>S</i> does not
    * denote a class available in the immediately enclosing scope.
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index aae070c..f18c8d2 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -1048,6 +1048,40 @@
   }
 
   @override
+  Object visitMixinDeclaration(MixinDeclaration node) {
+    // TODO(scheglov) Verify for all mixin errors.
+//    ClassElementImpl outerClass = _enclosingClass;
+    try {
+//      _isInNativeClass = node.nativeClause != null;
+//      _enclosingClass = AbstractClassElementImpl.getImpl(node.declaredElement);
+//      _checkDuplicateClassMembers(node);
+//      _checkForBuiltInIdentifierAsName(
+//          node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME);
+//      _checkForMemberWithClassName();
+//      _checkForNoDefaultSuperConstructorImplicit(node);
+//      _checkForConflictingTypeVariableErrorCodes(node);
+
+      OnClause onClause = node.onClause;
+      ImplementsClause implementsClause = node.implementsClause;
+
+      // Only do error checks only if there is a non-null clause.
+      if (onClause != null || implementsClause != null) {
+        _checkMixinInheritance(node, onClause, implementsClause);
+      }
+//      visitClassDeclarationIncrementally(node);
+//      _checkForFinalNotInitializedInClass(node);
+//      _checkForDuplicateDefinitionInheritance();
+//      _checkForConflictingInstanceMethodSetter(node);
+//      _checkForBadFunctionUse(node);
+      return super.visitMixinDeclaration(node);
+    } finally {
+//      _isInNativeClass = false;
+//      _initialFieldElementsMap = null;
+//      _enclosingClass = outerClass;
+    }
+  }
+
+  @override
   Object visitNativeClause(NativeClause node) {
     // TODO(brianwilkerson) Figure out the right rule for when 'native' is
     // allowed.
@@ -3280,8 +3314,7 @@
       return false;
     }
     if (typeName.isDeferred) {
-      _errorReporter
-          .reportErrorForNode(errorCode, typeName, [typeName.name.name]);
+      _errorReporter.reportErrorForNode(errorCode, typeName);
       return true;
     }
     return false;
@@ -4919,6 +4952,39 @@
   }
 
   /**
+   * Verify that all classes of the given [onClause] are valid.
+   *
+   * See [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR],
+   * [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT], and
+   * [CompileTimeErrorCode.MIXIN_REFERENCES_SUPER].
+   */
+  bool _checkForOnClauseErrorCodes(OnClause onClause) {
+    if (onClause == null) {
+      return false;
+    }
+    bool problemReported = false;
+    for (TypeName typeName in onClause.superclassConstraints) {
+      DartType type = typeName.type;
+      if (type is InterfaceType) {
+        if (_checkForExtendsOrImplementsDisallowedClass(
+            typeName,
+            CompileTimeErrorCode
+                .MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS)) {
+          problemReported = true;
+        } else {
+          if (_checkForExtendsOrImplementsDeferredClass(
+              typeName,
+              CompileTimeErrorCode
+                  .MIXIN_SUPER_CLASS_CONSTRAINT_DEFERRED_CLASS)) {
+            problemReported = true;
+          }
+        }
+      }
+    }
+    return problemReported;
+  }
+
+  /**
    * Verify the given operator-method [declaration], does not have an optional
    * parameter. This method assumes that the method declaration was tested to be
    * an operator declaration before being called.
@@ -5889,6 +5955,35 @@
   }
 
   /**
+   * Checks the class for problems with the superclass, mixins, or implemented
+   * interfaces.
+   */
+  void _checkMixinInheritance(MixinDeclaration node, OnClause onClause,
+      ImplementsClause implementsClause) {
+    // TODO(scheglov) Verify for all mixin errors.
+    // Only check for all of the inheritance logic around clauses if there
+    // isn't an error code such as "Cannot implement double" already.
+    if (!_checkForOnClauseErrorCodes(onClause) &&
+        !_checkForImplementsDisallowedClass(implementsClause)) {
+//      _checkForImplicitDynamicType(superclass);
+//      _checkForExtendsDeferredClass(superclass);
+      _checkForImplementsDeferredClass(implementsClause);
+//      _checkForNonAbstractClassInheritsAbstractMember(node.name);
+//      _checkForInconsistentMethodInheritance();
+//      _checkForRecursiveInterfaceInheritance(_enclosingClass);
+//      _checkForConflictingGetterAndMethod();
+//      _checkForConflictingInstanceGetterAndSuperclassMember();
+//      _checkImplementsSuperClass(implementsClause);
+//      _checkForMixinHasNoConstructors(node);
+//      _checkMixinInference(node, onClause);
+//      _checkForMixinWithConflictingPrivateMember(onClause, superclass);
+//      if (!disableConflictingGenericsCheck) {
+//        _checkForConflictingGenerics(node);
+//      }
+    }
+  }
+
+  /**
    * Verify that the given [typeArguments] are all within their bounds, as
    * defined by the given [element].
    *
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 8329fb9..957c45d6 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -9748,8 +9748,7 @@
       ErrorCode errorCode = (withClause == null
           ? CompileTimeErrorCode.EXTENDS_NON_CLASS
           : CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS);
-      superclassType = _resolveType(extendsClause.superclass, errorCode,
-          CompileTimeErrorCode.EXTENDS_ENUM, errorCode);
+      superclassType = _resolveType(extendsClause.superclass, errorCode);
     }
     if (classElement != null) {
       if (superclassType == null) {
@@ -9794,8 +9793,7 @@
   Object visitClassTypeAlias(ClassTypeAlias node) {
     super.visitClassTypeAlias(node);
     ErrorCode errorCode = CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS;
-    InterfaceType superclassType = _resolveType(node.superclass, errorCode,
-        CompileTimeErrorCode.EXTENDS_ENUM, errorCode);
+    InterfaceType superclassType = _resolveType(node.superclass, errorCode);
     if (superclassType == null) {
       superclassType = typeProvider.objectType;
     }
@@ -10261,11 +10259,8 @@
       ClassElementImpl classElement, ImplementsClause clause) {
     if (clause != null) {
       NodeList<TypeName> interfaces = clause.interfaces;
-      List<InterfaceType> interfaceTypes = _resolveTypes(
-          interfaces,
-          CompileTimeErrorCode.IMPLEMENTS_NON_CLASS,
-          CompileTimeErrorCode.IMPLEMENTS_ENUM,
-          CompileTimeErrorCode.IMPLEMENTS_DYNAMIC);
+      List<InterfaceType> interfaceTypes =
+          _resolveTypes(interfaces, CompileTimeErrorCode.IMPLEMENTS_NON_CLASS);
       if (classElement != null) {
         classElement.interfaces = interfaceTypes;
       }
@@ -10298,12 +10293,10 @@
   void _resolveOnClause(MixinElementImpl classElement, OnClause clause) {
     List<InterfaceType> types;
     if (clause != null) {
-      types = _resolveTypes(
-          clause.superclassConstraints,
-          CompileTimeErrorCode.MIXIN_OF_NON_CLASS,
-          CompileTimeErrorCode.MIXIN_OF_ENUM,
-          CompileTimeErrorCode.MIXIN_OF_NON_CLASS);
-    } else {
+      types = _resolveTypes(clause.superclassConstraints,
+          CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_CLASS);
+    }
+    if (types == null || types.isEmpty) {
       types = [typeProvider.objectType];
     }
     classElement.superclassConstraints = types;
@@ -10319,13 +10312,12 @@
    * @param dynamicTypeError the error to produce if the type name is "dynamic"
    * @return the type specified by the type name
    */
-  InterfaceType _resolveType(TypeName typeName, ErrorCode nonTypeError,
-      ErrorCode enumTypeError, ErrorCode dynamicTypeError) {
+  InterfaceType _resolveType(TypeName typeName, ErrorCode errorCode) {
     DartType type = typeName.type;
     if (type is InterfaceType) {
       ClassElement element = type.element;
       if (element != null && element.isEnum) {
-        errorReporter.reportErrorForNode(enumTypeError, typeName);
+        errorReporter.reportErrorForNode(errorCode, typeName);
         return null;
       }
       return type;
@@ -10333,14 +10325,8 @@
     // If the type is not an InterfaceType, then visitTypeName() sets the type
     // to be a DynamicTypeImpl
     Identifier name = typeName.name;
-    // TODO(mfairhurst) differentiate between dynamic via clean path, and error
-    // types, and then check `type.isDynamic`. However, if we do that now, then
-    // [nonTypeError] will never be reported because non types are resolved to
-    // dynamic.
-    if (name.name == Keyword.DYNAMIC.lexeme) {
-      errorReporter.reportErrorForNode(dynamicTypeError, name, [name.name]);
-    } else if (!nameScope.shouldIgnoreUndefined(name)) {
-      errorReporter.reportErrorForNode(nonTypeError, name, [name.name]);
+    if (!nameScope.shouldIgnoreUndefined(name)) {
+      errorReporter.reportErrorForNode(errorCode, name, [name.name]);
     }
     return null;
   }
@@ -10356,14 +10342,10 @@
    * @return an array containing all of the types that were resolved.
    */
   List<InterfaceType> _resolveTypes(
-      NodeList<TypeName> typeNames,
-      ErrorCode nonTypeError,
-      ErrorCode enumTypeError,
-      ErrorCode dynamicTypeError) {
+      NodeList<TypeName> typeNames, ErrorCode errorCode) {
     List<InterfaceType> types = new List<InterfaceType>();
     for (TypeName typeName in typeNames) {
-      InterfaceType type =
-          _resolveType(typeName, nonTypeError, enumTypeError, dynamicTypeError);
+      InterfaceType type = _resolveType(typeName, errorCode);
       if (type != null) {
         types.add(type);
       }
@@ -10374,10 +10356,7 @@
   void _resolveWithClause(ClassElementImpl classElement, WithClause clause) {
     if (clause != null) {
       List<InterfaceType> mixinTypes = _resolveTypes(
-          clause.mixinTypes,
-          CompileTimeErrorCode.MIXIN_OF_NON_CLASS,
-          CompileTimeErrorCode.MIXIN_OF_ENUM,
-          CompileTimeErrorCode.MIXIN_OF_NON_CLASS);
+          clause.mixinTypes, CompileTimeErrorCode.MIXIN_OF_NON_CLASS);
       classElement.mixins = mixinTypes;
     }
   }
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
index 5aac04e..4d6b0b7 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -2320,26 +2320,26 @@
     verify([source]);
   }
 
-  test_extendsEnum() async {
-    Source source = addSource(r'''
-enum E { ONE }
-class A extends E {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.EXTENDS_ENUM]);
-    verify([source]);
-  }
-
-  test_extendsNonClass_class() async {
-    Source source = addSource(r'''
-int A;
-class B extends A {}''');
+  test_extendsNonClass_dynamic() async {
+    Source source = addSource("class B extends dynamic {}");
     await computeAnalysisResult(source);
     assertErrors(source, [CompileTimeErrorCode.EXTENDS_NON_CLASS]);
     verify([source]);
   }
 
-  test_extendsNonClass_dynamic() async {
-    Source source = addSource("class B extends dynamic {}");
+  test_extendsNonClass_enum() async {
+    Source source = addSource(r'''
+enum E { ONE }
+class A extends E {}''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [CompileTimeErrorCode.EXTENDS_NON_CLASS]);
+    verify([source]);
+  }
+
+  test_extendsNonClass_variable() async {
+    Source source = addSource(r'''
+int A;
+class B extends A {}''');
     await computeAnalysisResult(source);
     assertErrors(source, [CompileTimeErrorCode.EXTENDS_NON_CLASS]);
     verify([source]);
@@ -3003,22 +3003,6 @@
     verify([source]);
   }
 
-  test_implementsDynamic() async {
-    Source source = addSource("class A implements dynamic {}");
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_DYNAMIC]);
-    verify([source]);
-  }
-
-  test_implementsEnum() async {
-    Source source = addSource(r'''
-enum E { ONE }
-class A implements E {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_ENUM]);
-    verify([source]);
-  }
-
   test_implementsNonClass_class() async {
     Source source = addSource(r'''
 int A;
@@ -3028,6 +3012,22 @@
     verify([source]);
   }
 
+  test_implementsNonClass_dynamic() async {
+    Source source = addSource("class A implements dynamic {}");
+    await computeAnalysisResult(source);
+    assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_NON_CLASS]);
+    verify([source]);
+  }
+
+  test_implementsNonClass_enum() async {
+    Source source = addSource(r'''
+enum E { ONE }
+class A implements E {}''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [CompileTimeErrorCode.IMPLEMENTS_NON_CLASS]);
+    verify([source]);
+  }
+
   test_implementsNonClass_typeAlias() async {
     Source source = addSource(r'''
 class A {}
@@ -4535,15 +4535,6 @@
     verify([source]);
   }
 
-  test_mixinOfEnum() async {
-    Source source = addSource(r'''
-enum E { ONE }
-class A extends Object with E {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_ENUM]);
-    verify([source]);
-  }
-
   @failingTest
   test_mixinOfNonClass() async {
     // TODO(brianwilkerson) Compare with MIXIN_WITH_NON_CLASS_SUPERCLASS.
@@ -4564,6 +4555,15 @@
     verify([source]);
   }
 
+  test_mixinOfNonClass_enum() async {
+    Source source = addSource(r'''
+enum E { ONE }
+class A extends Object with E {}''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [CompileTimeErrorCode.MIXIN_OF_NON_CLASS]);
+    verify([source]);
+  }
+
   test_mixinOfNonClass_typeAlias() async {
     Source source = addSource(r'''
 class A {}
diff --git a/pkg/analyzer/test/src/context/mock_sdk.dart b/pkg/analyzer/test/src/context/mock_sdk.dart
index aa03f21..73c70d6 100644
--- a/pkg/analyzer/test/src/context/mock_sdk.dart
+++ b/pkg/analyzer/test/src/context/mock_sdk.dart
@@ -321,7 +321,7 @@
 class Duration implements Comparable<Duration> {}
 
 class Exception {
-  factory Exception([var message]);
+  factory Exception([var message]) => null;
 }
 
 external bool identical(Object a, Object b);
diff --git a/pkg/analyzer/test/src/dart/resolution/find_element.dart b/pkg/analyzer/test/src/dart/resolution/find_element.dart
index ff87f0e..df7c82b 100644
--- a/pkg/analyzer/test/src/dart/resolution/find_element.dart
+++ b/pkg/analyzer/test/src/dart/resolution/find_element.dart
@@ -21,6 +21,15 @@
     fail('Not found class: $name');
   }
 
+  ClassElement enum_(String name) {
+    for (var enum_ in unitElement.enums) {
+      if (enum_.name == name) {
+        return enum_;
+      }
+    }
+    fail('Not found enum: $name');
+  }
+
   ExportElement export(String targetUri) {
     ExportElement exportElement;
     for (var export in unitElement.library.exports) {
diff --git a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
index 205c71f..047499e 100644
--- a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
@@ -1,3 +1,4 @@
+import 'package:analyzer/src/error/codes.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -12,7 +13,11 @@
   });
 }
 
-abstract class AssignmentResolutionMixin implements ResolutionTest {
+@reflectiveTest
+class MixinDriverResolutionTest extends DriverResolutionTest
+    with MixinResolutionMixin {}
+
+abstract class MixinResolutionMixin implements ResolutionTest {
   test_accessor_getter() async {
     addTestFile(r'''
 mixin M {
@@ -20,6 +25,7 @@
 }
 ''');
     await resolveTestFile();
+    assertNoTestErrors();
 
     var element = findElement.mixin('M');
 
@@ -44,6 +50,7 @@
 }
 ''');
     await resolveTestFile();
+    assertNoTestErrors();
 
     var element = findElement.mixin('M');
 
@@ -64,6 +71,7 @@
 }
 ''');
     await resolveTestFile();
+    assertNoTestErrors();
 
     var element = findElement.mixin('M');
 
@@ -89,6 +97,7 @@
 mixin M {}
 ''');
     await resolveTestFile();
+    assertNoTestErrors();
 
     var aRef = findNode.commentReference('a]').identifier;
     assertElement(aRef, findElement.topGet('a'));
@@ -100,6 +109,7 @@
 mixin M {}
 ''');
     await resolveTestFile();
+    assertNoTestErrors();
 
     var mixin = findNode.mixin('mixin M');
     var element = findElement.mixin('M');
@@ -109,6 +119,151 @@
     assertElementTypes(element.superclassConstraints, [objectType]);
   }
 
+  test_error_implementsClause_deferredClass() async {
+    addTestFile(r'''
+import 'dart:math' deferred as math;
+mixin M implements math.Random {}
+''');
+    await resolveTestFile();
+    var mathImport = findElement.import('dart:math');
+    var randomElement = mathImport.importedLibrary.getType('Random');
+
+    assertTestErrors([
+      CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS,
+    ]);
+
+    var element = findElement.mixin('M');
+    assertElementTypes(element.interfaces, [randomElement.type]);
+
+    var typeRef = findNode.typeName('Random {}');
+    assertTypeName(typeRef, randomElement, 'Random',
+        expectedPrefix: mathImport.prefix);
+  }
+
+  test_error_implementsClause_disallowedClass_int() async {
+    addTestFile(r'''
+mixin M implements int {}
+''');
+    await resolveTestFile();
+
+    assertTestErrors([
+      CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS,
+    ]);
+
+    var element = findElement.mixin('M');
+    assertElementTypes(element.interfaces, [intType]);
+
+    var typeRef = findNode.typeName('int {}');
+    assertTypeName(typeRef, intElement, 'int');
+  }
+
+  test_error_implementsClause_nonClass_void() async {
+    addTestFile(r'''
+mixin M implements void {}
+''');
+    await resolveTestFile();
+
+    assertTestErrors([
+      CompileTimeErrorCode.IMPLEMENTS_NON_CLASS,
+    ]);
+
+    var element = findElement.mixin('M');
+    assertElementTypes(element.interfaces, []);
+
+    var typeRef = findNode.typeName('void {}');
+    assertTypeName(typeRef, null, 'void');
+  }
+
+  test_error_onClause_deferredClass() async {
+    addTestFile(r'''
+import 'dart:math' deferred as math;
+mixin M on math.Random {}
+''');
+    await resolveTestFile();
+    var mathImport = findElement.import('dart:math');
+    var randomElement = mathImport.importedLibrary.getType('Random');
+
+    assertTestErrors([
+      CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DEFERRED_CLASS,
+    ]);
+
+    var element = findElement.mixin('M');
+    assertElementTypes(element.superclassConstraints, [randomElement.type]);
+
+    var typeRef = findNode.typeName('Random {}');
+    assertTypeName(typeRef, randomElement, 'Random',
+        expectedPrefix: mathImport.prefix);
+  }
+
+  test_error_onClause_disallowedClass_int() async {
+    addTestFile(r'''
+mixin M on int {}
+''');
+    await resolveTestFile();
+
+    assertTestErrors([
+      CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS,
+    ]);
+
+    var element = findElement.mixin('M');
+    assertElementTypes(element.superclassConstraints, [intType]);
+
+    var typeRef = findNode.typeName('int {}');
+    assertTypeName(typeRef, intElement, 'int');
+  }
+
+  test_error_onClause_nonClass_dynamic() async {
+    addTestFile(r'''
+mixin M on dynamic {}
+''');
+    await resolveTestFile();
+
+    assertTestErrors([
+      CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_CLASS,
+    ]);
+
+    var element = findElement.mixin('M');
+    assertElementTypes(element.superclassConstraints, [objectType]);
+
+    var typeRef = findNode.typeName('dynamic {}');
+    assertTypeName(typeRef, dynamicElement, 'dynamic');
+  }
+
+  test_error_onClause_nonClass_enum() async {
+    addTestFile(r'''
+enum E {E1, E2, E3}
+mixin M on E {}
+''');
+    await resolveTestFile();
+
+    assertTestErrors([
+      CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_CLASS,
+    ]);
+
+    var element = findElement.mixin('M');
+    assertElementTypes(element.superclassConstraints, [objectType]);
+
+    var typeRef = findNode.typeName('E {}');
+    assertTypeName(typeRef, findElement.enum_('E'), 'E');
+  }
+
+  test_error_onClause_nonClass_void() async {
+    addTestFile(r'''
+mixin M on void {}
+''');
+    await resolveTestFile();
+
+    assertTestErrors([
+      CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_CLASS,
+    ]);
+
+    var element = findElement.mixin('M');
+    assertElementTypes(element.superclassConstraints, [objectType]);
+
+    var typeRef = findNode.typeName('void {}');
+    assertTypeName(typeRef, null, 'void');
+  }
+
   test_field() async {
     addTestFile(r'''
 mixin M<T> {
@@ -116,6 +271,7 @@
 }
 ''');
     await resolveTestFile();
+    assertNoTestErrors();
 
     var element = findElement.mixin('M');
 
@@ -155,6 +311,7 @@
 mixin M implements A, B {} // M
 ''');
     await resolveTestFile();
+    assertNoTestErrors();
 
     var element = findElement.mixin('M');
     assertElementTypes(element.interfaces, [
@@ -177,6 +334,7 @@
 mixin M {}
 ''');
     await resolveTestFile();
+    assertNoTestErrors();
 
     var a = findElement.topGet('a');
     var element = findElement.mixin('M');
@@ -198,6 +356,7 @@
 mixin M on A, B {} // M
 ''');
     await resolveTestFile();
+    assertNoTestErrors();
 
     var element = findElement.mixin('M');
     assertElementTypes(element.superclassConstraints, [
@@ -214,9 +373,5 @@
 }
 
 @reflectiveTest
-class MixinDriverResolutionTest extends DriverResolutionTest
-    with AssignmentResolutionMixin {}
-
-@reflectiveTest
 class MixinTaskResolutionTest extends TaskResolutionTest
-    with AssignmentResolutionMixin {}
+    with MixinResolutionMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index b93718a..a7751c1 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -6,10 +6,12 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:test/test.dart';
 
+import '../../../generated/test_support.dart';
 import 'find_element.dart';
 import 'find_node.dart';
 
@@ -31,6 +33,8 @@
 
   InterfaceType get doubleType => typeProvider.doubleType;
 
+  Element get dynamicElement => typeProvider.dynamicType.element;
+
   ClassElement get intElement => typeProvider.intType.element;
 
   InterfaceType get intType => typeProvider.intType;
@@ -84,6 +88,31 @@
     expect(element.enclosingElement, expectedEnclosing);
   }
 
+  /**
+   * Assert that the number of error codes in reported [errors] matches the
+   * number of [expected] error codes. The order of errors is ignored.
+   */
+  void assertErrors(List<AnalysisError> errors,
+      [List<ErrorCode> expected = const <ErrorCode>[]]) {
+    var errorListener = new GatheringErrorListener();
+    for (AnalysisError error in result.errors) {
+      ErrorCode errorCode = error.errorCode;
+      if (errorCode == HintCode.UNUSED_CATCH_CLAUSE ||
+          errorCode == HintCode.UNUSED_CATCH_STACK ||
+          errorCode == HintCode.UNUSED_ELEMENT ||
+          errorCode == HintCode.UNUSED_FIELD ||
+          errorCode == HintCode.UNUSED_LOCAL_VARIABLE) {
+        continue;
+      }
+      errorListener.onError(error);
+    }
+    errorListener.assertErrorsWithCodes(expected);
+  }
+
+  void assertHasTestErrors() {
+    expect(result.errors, isNotEmpty);
+  }
+
   void assertIdentifierTopGetRef(SimpleIdentifier ref, String name) {
     var getter = findElement.topGet(name);
     assertElement(ref, getter);
@@ -107,6 +136,14 @@
     expect(actual.baseElement, same(expectedBase));
   }
 
+  void assertNoTestErrors() {
+    expect(result.errors, isEmpty);
+  }
+
+  void assertTestErrors(List<ErrorCode> expected) {
+    assertErrors(result.errors, expected);
+  }
+
   void assertTopGetRef(String search, String name) {
     var ref = findNode.simple(search);
     assertIdentifierTopGetRef(ref, name);
@@ -179,7 +216,7 @@
 
   Future<TestAnalysisResult> resolveFile(String path);
 
-  Future resolveTestFile() async {
+  Future<void> resolveTestFile() async {
     var path = convertPath('/test/lib/test.dart');
     result = await resolveFile(path);
     findNode = new FindNode(result.content, result.unit);
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart
new file mode 100644
index 0000000..51477cf
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'assignment_test.dart' as assignment_test;
+import 'mixin_test.dart' as mixin_test;
+
+main() {
+  defineReflectiveSuite(() {
+    assignment_test.main();
+    mixin_test.main();
+  }, name: 'resolution');
+}
diff --git a/pkg/analyzer/test/src/dart/test_all.dart b/pkg/analyzer/test/src/dart/test_all.dart
index 78ac68f..7855e3e 100644
--- a/pkg/analyzer/test/src/dart/test_all.dart
+++ b/pkg/analyzer/test/src/dart/test_all.dart
@@ -10,6 +10,7 @@
 import 'ast/test_all.dart' as ast;
 import 'constant/test_all.dart' as constant;
 import 'element/test_all.dart' as element;
+import 'resolution/test_all.dart' as resolution;
 import 'sdk/test_all.dart' as sdk;
 
 /// Utility for manually running all tests.
@@ -19,6 +20,7 @@
     ast.main();
     constant.main();
     element.main();
+    resolution.main();
     sdk.main();
   }, name: 'dart');
 }