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