Check for conflicts in mixins

Change-Id: I5443508d8454b2c903b65e253ecda223485787ad
Reviewed-on: https://dart-review.googlesource.com/c/88945
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
diff --git a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
index 5221ddd..4d5c736 100644
--- a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
@@ -230,6 +230,10 @@
     Scope scope = cls.scope;
     if (cls.isMixinApplication) {
       Declaration mixin = getDeclaration(cls.mixedInType);
+      while (mixin.isNamedMixinApplication) {
+        KernelClassBuilder named = mixin;
+        mixin = getDeclaration(named.mixedInType);
+      }
       if (mixin is KernelClassBuilder) {
         scope = mixin.scope;
       }
@@ -290,6 +294,13 @@
       merge(cls, localSetters, classMembers, MergeKind.accessors);
 
       List<KernelTypeBuilder> interfaces = cls.interfaces;
+      if (cls.isMixinApplication) {
+        if (interfaces == null) {
+          interfaces = <KernelTypeBuilder>[cls.mixedInType];
+        } else {
+          interfaces = <KernelTypeBuilder>[cls.mixedInType]..addAll(interfaces);
+        }
+      }
       if (interfaces != null) {
         MergeResult result = mergeInterfaces(cls, supernode, interfaces);
         interfaceMembers = result.mergedMembers;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
index 77098cf..a407da3 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
@@ -1362,7 +1362,7 @@
   }
 
   String get fullNameForErrors {
-    return isMixinApplication
+    return isMixinApplication && !isNamedMixinApplication
         ? "${supertype.fullNameForErrors} with ${mixedInType.fullNameForErrors}"
         : name;
   }
diff --git a/pkg/front_end/testcases/mixin_conflicts.dart b/pkg/front_end/testcases/mixin_conflicts.dart
new file mode 100644
index 0000000..6afebe0
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_conflicts.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2019, 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.
+
+// This class has no problems.
+class M {
+  foo() {}
+}
+
+// This class has no problems.
+class N = Object with M;
+
+// This class has no problems.
+class C extends Object with N {}
+
+// This class has no problems.
+abstract class M2 implements M {
+  bar() {}
+}
+
+// This class has an error as it lacks an implementation of M.foo.
+class N2 = Object with M2;
+
+// This class lacks an implementation of M.foo, but it is abstract so there's
+// no error.
+abstract class N3 = Object with M2;
+
+// This class has an error as it lacks an implementation of M.foo.
+class C2 extends Object with M2 {}
+
+// This class lacks an implementation of M.foo, but it is abstract so there's
+// no error.
+abstract class C3 extends Object with M2 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/mixin_conflicts.dart.legacy.expect b/pkg/front_end/testcases/mixin_conflicts.dart.legacy.expect
new file mode 100644
index 0000000..d27c051
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_conflicts.dart.legacy.expect
@@ -0,0 +1,116 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/mixin_conflicts.dart:22:7: Error: The non-abstract class 'N2' is missing implementations for these members:
+//  - M.foo
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class N2 = Object with M2;
+//       ^^
+// pkg/front_end/testcases/mixin_conflicts.dart:7:3: Context: 'M.foo' is defined here.
+//   foo() {}
+//   ^^^
+//
+// pkg/front_end/testcases/mixin_conflicts.dart:29:7: Error: The non-abstract class 'C2' is missing implementations for these members:
+//  - M.foo
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class C2 extends Object with M2 {}
+//       ^^
+// pkg/front_end/testcases/mixin_conflicts.dart:7:3: Context: 'M.foo' is defined here.
+//   foo() {}
+//   ^^^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/mixin_conflicts.dart:22:7: Error: The non-abstract class 'N2' is missing implementations for these members:
+//  - M.foo
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+// 
+// class N2 = Object with M2;
+//       ^^
+//
+// pkg/front_end/testcases/mixin_conflicts.dart:29:7: Error: The non-abstract class 'C2' is missing implementations for these members:
+//  - M.foo
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+// 
+// class C2 extends Object with M2 {}
+//       ^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class M extends core::Object {
+  synthetic constructor •() → self::M
+    : super core::Object::•()
+    ;
+  method foo() → dynamic {}
+}
+class N = core::Object with self::M {
+  const synthetic constructor •() → self::N
+    : super core::Object::•()
+    ;
+}
+abstract class _C&Object&N = core::Object with self::N {
+  const synthetic constructor •() → self::_C&Object&N
+    : super core::Object::•()
+    ;
+}
+class C extends self::_C&Object&N {
+  synthetic constructor •() → self::C
+    : super self::_C&Object&N::•()
+    ;
+}
+abstract class M2 extends core::Object implements self::M {
+  synthetic constructor •() → self::M2
+    : super core::Object::•()
+    ;
+  method bar() → dynamic {}
+}
+class N2 = core::Object with self::M2 {
+  const synthetic constructor •() → self::N2
+    : super core::Object::•()
+    ;
+}
+abstract class N3 = core::Object with self::M2 {
+  const synthetic constructor •() → self::N3
+    : super core::Object::•()
+    ;
+}
+abstract class _C2&Object&M2 = core::Object with self::M2 {
+  const synthetic constructor •() → self::_C2&Object&M2
+    : super core::Object::•()
+    ;
+}
+class C2 extends self::_C2&Object&M2 {
+  synthetic constructor •() → self::C2
+    : super self::_C2&Object&M2::•()
+    ;
+}
+abstract class _C3&Object&M2 = core::Object with self::M2 {
+  const synthetic constructor •() → self::_C3&Object&M2
+    : super core::Object::•()
+    ;
+}
+abstract class C3 extends self::_C3&Object&M2 {
+  synthetic constructor •() → self::C3
+    : super self::_C3&Object&M2::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/mixin_conflicts.dart.legacy.transformed.expect b/pkg/front_end/testcases/mixin_conflicts.dart.legacy.transformed.expect
new file mode 100644
index 0000000..998839d
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_conflicts.dart.legacy.transformed.expect
@@ -0,0 +1,92 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/mixin_conflicts.dart:22:7: Error: The non-abstract class 'N2' is missing implementations for these members:
+//  - M.foo
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+// 
+// class N2 = Object with M2;
+//       ^^
+//
+// pkg/front_end/testcases/mixin_conflicts.dart:29:7: Error: The non-abstract class 'C2' is missing implementations for these members:
+//  - M.foo
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+// 
+// class C2 extends Object with M2 {}
+//       ^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class M extends core::Object {
+  synthetic constructor •() → self::M
+    : super core::Object::•()
+    ;
+  method foo() → dynamic {}
+}
+class N extends core::Object implements self::M {
+  const synthetic constructor •() → self::N
+    : super core::Object::•()
+    ;
+  method foo() → dynamic {}
+}
+abstract class _C&Object&N extends core::Object implements self::N {
+  const synthetic constructor •() → self::_C&Object&N
+    : super core::Object::•()
+    ;
+  method foo() → dynamic {}
+}
+class C extends self::_C&Object&N {
+  synthetic constructor •() → self::C
+    : super self::_C&Object&N::•()
+    ;
+}
+abstract class M2 extends core::Object implements self::M {
+  synthetic constructor •() → self::M2
+    : super core::Object::•()
+    ;
+  method bar() → dynamic {}
+}
+class N2 extends core::Object implements self::M2 {
+  const synthetic constructor •() → self::N2
+    : super core::Object::•()
+    ;
+  method bar() → dynamic {}
+}
+abstract class N3 extends core::Object implements self::M2 {
+  const synthetic constructor •() → self::N3
+    : super core::Object::•()
+    ;
+  method bar() → dynamic {}
+}
+abstract class _C2&Object&M2 extends core::Object implements self::M2 {
+  const synthetic constructor •() → self::_C2&Object&M2
+    : super core::Object::•()
+    ;
+  method bar() → dynamic {}
+}
+class C2 extends self::_C2&Object&M2 {
+  synthetic constructor •() → self::C2
+    : super self::_C2&Object&M2::•()
+    ;
+}
+abstract class _C3&Object&M2 extends core::Object implements self::M2 {
+  const synthetic constructor •() → self::_C3&Object&M2
+    : super core::Object::•()
+    ;
+  method bar() → dynamic {}
+}
+abstract class C3 extends self::_C3&Object&M2 {
+  synthetic constructor •() → self::C3
+    : super self::_C3&Object&M2::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/mixin_conflicts.dart.outline.expect b/pkg/front_end/testcases/mixin_conflicts.dart.outline.expect
new file mode 100644
index 0000000..603394f
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_conflicts.dart.outline.expect
@@ -0,0 +1,90 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/mixin_conflicts.dart:22:7: Error: The non-abstract class 'N2' is missing implementations for these members:
+//  - M.foo
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class N2 = Object with M2;
+//       ^^
+// pkg/front_end/testcases/mixin_conflicts.dart:7:3: Context: 'M.foo' is defined here.
+//   foo() {}
+//   ^^^
+//
+// pkg/front_end/testcases/mixin_conflicts.dart:29:7: Error: The non-abstract class 'C2' is missing implementations for these members:
+//  - M.foo
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class C2 extends Object with M2 {}
+//       ^^
+// pkg/front_end/testcases/mixin_conflicts.dart:7:3: Context: 'M.foo' is defined here.
+//   foo() {}
+//   ^^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class M extends core::Object {
+  synthetic constructor •() → self::M
+    ;
+  method foo() → dynamic
+    ;
+}
+class N = core::Object with self::M {
+  const synthetic constructor •() → self::N
+    : super core::Object::•()
+    ;
+}
+abstract class _C&Object&N = core::Object with self::N {
+  const synthetic constructor •() → self::_C&Object&N
+    : super core::Object::•()
+    ;
+}
+class C extends self::_C&Object&N {
+  synthetic constructor •() → self::C
+    ;
+}
+abstract class M2 extends core::Object implements self::M {
+  synthetic constructor •() → self::M2
+    ;
+  method bar() → dynamic
+    ;
+}
+class N2 = core::Object with self::M2 {
+  const synthetic constructor •() → self::N2
+    : super core::Object::•()
+    ;
+}
+abstract class N3 = core::Object with self::M2 {
+  const synthetic constructor •() → self::N3
+    : super core::Object::•()
+    ;
+}
+abstract class _C2&Object&M2 = core::Object with self::M2 {
+  const synthetic constructor •() → self::_C2&Object&M2
+    : super core::Object::•()
+    ;
+}
+class C2 extends self::_C2&Object&M2 {
+  synthetic constructor •() → self::C2
+    ;
+}
+abstract class _C3&Object&M2 = core::Object with self::M2 {
+  const synthetic constructor •() → self::_C3&Object&M2
+    : super core::Object::•()
+    ;
+}
+abstract class C3 extends self::_C3&Object&M2 {
+  synthetic constructor •() → self::C3
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/mixin_conflicts.dart.strong.expect b/pkg/front_end/testcases/mixin_conflicts.dart.strong.expect
new file mode 100644
index 0000000..7289621
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_conflicts.dart.strong.expect
@@ -0,0 +1,116 @@
+// Formatted problems:
+//
+// pkg/front_end/testcases/mixin_conflicts.dart:22:7: Error: The non-abstract class 'N2' is missing implementations for these members:
+//  - 'foo'
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class N2 = Object with M2;
+//       ^^
+// pkg/front_end/testcases/mixin_conflicts.dart:7:3: Context: 'foo' is defined here.
+//   foo() {}
+//   ^^^
+//
+// pkg/front_end/testcases/mixin_conflicts.dart:29:7: Error: The non-abstract class 'C2' is missing implementations for these members:
+//  - 'foo'
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+//
+// class C2 extends Object with M2 {}
+//       ^^
+// pkg/front_end/testcases/mixin_conflicts.dart:7:3: Context: 'foo' is defined here.
+//   foo() {}
+//   ^^^
+
+// Unhandled errors:
+//
+// pkg/front_end/testcases/mixin_conflicts.dart:22:7: Error: The non-abstract class 'N2' is missing implementations for these members:
+//  - 'foo'
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+// 
+// class N2 = Object with M2;
+//       ^^
+//
+// pkg/front_end/testcases/mixin_conflicts.dart:29:7: Error: The non-abstract class 'C2' is missing implementations for these members:
+//  - 'foo'
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+// 
+// class C2 extends Object with M2 {}
+//       ^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class M extends core::Object {
+  synthetic constructor •() → self::M
+    : super core::Object::•()
+    ;
+  method foo() → dynamic {}
+}
+class N = core::Object with self::M {
+  const synthetic constructor •() → self::N
+    : super core::Object::•()
+    ;
+}
+abstract class _C&Object&N = core::Object with self::N {
+  const synthetic constructor •() → self::_C&Object&N
+    : super core::Object::•()
+    ;
+}
+class C extends self::_C&Object&N {
+  synthetic constructor •() → self::C
+    : super self::_C&Object&N::•()
+    ;
+}
+abstract class M2 extends core::Object implements self::M {
+  synthetic constructor •() → self::M2
+    : super core::Object::•()
+    ;
+  method bar() → dynamic {}
+}
+class N2 = core::Object with self::M2 {
+  const synthetic constructor •() → self::N2
+    : super core::Object::•()
+    ;
+}
+abstract class N3 = core::Object with self::M2 {
+  const synthetic constructor •() → self::N3
+    : super core::Object::•()
+    ;
+}
+abstract class _C2&Object&M2 = core::Object with self::M2 {
+  const synthetic constructor •() → self::_C2&Object&M2
+    : super core::Object::•()
+    ;
+}
+class C2 extends self::_C2&Object&M2 {
+  synthetic constructor •() → self::C2
+    : super self::_C2&Object&M2::•()
+    ;
+}
+abstract class _C3&Object&M2 = core::Object with self::M2 {
+  const synthetic constructor •() → self::_C3&Object&M2
+    : super core::Object::•()
+    ;
+}
+abstract class C3 extends self::_C3&Object&M2 {
+  synthetic constructor •() → self::C3
+    : super self::_C3&Object&M2::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/mixin_conflicts.dart.strong.transformed.expect b/pkg/front_end/testcases/mixin_conflicts.dart.strong.transformed.expect
new file mode 100644
index 0000000..fb7b2b1
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_conflicts.dart.strong.transformed.expect
@@ -0,0 +1,92 @@
+// Unhandled errors:
+//
+// pkg/front_end/testcases/mixin_conflicts.dart:22:7: Error: The non-abstract class 'N2' is missing implementations for these members:
+//  - 'foo'
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+// 
+// class N2 = Object with M2;
+//       ^^
+//
+// pkg/front_end/testcases/mixin_conflicts.dart:29:7: Error: The non-abstract class 'C2' is missing implementations for these members:
+//  - 'foo'
+// Try to either
+//  - provide an implementation,
+//  - inherit an implementation from a superclass or mixin,
+//  - mark the class as abstract, or
+//  - provide a 'noSuchMethod' implementation.
+// 
+// class C2 extends Object with M2 {}
+//       ^^
+
+library;
+import self as self;
+import "dart:core" as core;
+
+class M extends core::Object {
+  synthetic constructor •() → self::M
+    : super core::Object::•()
+    ;
+  method foo() → dynamic {}
+}
+class N extends core::Object implements self::M {
+  const synthetic constructor •() → self::N
+    : super core::Object::•()
+    ;
+  method foo() → dynamic {}
+}
+abstract class _C&Object&N extends core::Object implements self::N {
+  const synthetic constructor •() → self::_C&Object&N
+    : super core::Object::•()
+    ;
+  method foo() → dynamic {}
+}
+class C extends self::_C&Object&N {
+  synthetic constructor •() → self::C
+    : super self::_C&Object&N::•()
+    ;
+}
+abstract class M2 extends core::Object implements self::M {
+  synthetic constructor •() → self::M2
+    : super core::Object::•()
+    ;
+  method bar() → dynamic {}
+}
+class N2 extends core::Object implements self::M2 {
+  const synthetic constructor •() → self::N2
+    : super core::Object::•()
+    ;
+  method bar() → dynamic {}
+}
+abstract class N3 extends core::Object implements self::M2 {
+  const synthetic constructor •() → self::N3
+    : super core::Object::•()
+    ;
+  method bar() → dynamic {}
+}
+abstract class _C2&Object&M2 extends core::Object implements self::M2 {
+  const synthetic constructor •() → self::_C2&Object&M2
+    : super core::Object::•()
+    ;
+  method bar() → dynamic {}
+}
+class C2 extends self::_C2&Object&M2 {
+  synthetic constructor •() → self::C2
+    : super self::_C2&Object&M2::•()
+    ;
+}
+abstract class _C3&Object&M2 extends core::Object implements self::M2 {
+  const synthetic constructor •() → self::_C3&Object&M2
+    : super core::Object::•()
+    ;
+  method bar() → dynamic {}
+}
+abstract class C3 extends self::_C3&Object&M2 {
+  synthetic constructor •() → self::C3
+    : super self::_C3&Object&M2::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index c4a93e2..0a3ca37 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -675,6 +675,7 @@
 minimum_int: TextSerializationFailure # Was: Pass
 missing_constructor: TextSerializationFailure # Was: Pass
 mixin_application_override: TypeCheckError
+mixin_conflicts: TextSerializationFailure
 mixin_constructors_with_default_values: TextSerializationFailure # Was: Pass
 mixin_inherited_setter_for_mixed_in_field: TextSerializationFailure # Was: Pass
 mixin_super_repeated: TextSerializationFailure # Was: Pass