Report InheritedMembersConflict correctly
Notice that no conflict is reported when an inherited
setter is in conflict with an inherited member. This is
implemented in a later CL.
Before we would only use InheritedMembersConflict when merging
interfaces, but as the new test cases demonstrate, that's not
sufficient.
Change-Id: I690dde1b59499d3ee0967b3f118b0b3b58898442
Reviewed-on: https://dart-review.googlesource.com/c/88941
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 505559d..5ee5ae1 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
@@ -93,7 +93,7 @@
return a;
}
if (isInheritanceConflict(a, b)) {
- reportInheritanceConflict(cls, a, b, mergeKind);
+ reportInheritanceConflict(cls, a, b);
}
Declaration result = a;
if (mergeKind == MergeKind.interfaces) {
@@ -120,10 +120,10 @@
return result;
}
- void reportInheritanceConflict(KernelClassBuilder cls, Declaration a,
- Declaration b, MergeKind mergeKind) {
+ void reportInheritanceConflict(
+ KernelClassBuilder cls, Declaration a, Declaration b) {
String name = a.fullNameForErrors;
- if (mergeKind == MergeKind.interfaces) {
+ if (a.parent != cls) {
cls.addProblem(messageInheritedMembersConflict, cls.charOffset,
cls.fullNameForErrors.length,
context: <LocatedMessage>[
diff --git a/pkg/front_end/testcases/abstract_members.dart b/pkg/front_end/testcases/abstract_members.dart
index 058cbe9..86b3dae 100644
--- a/pkg/front_end/testcases/abstract_members.dart
+++ b/pkg/front_end/testcases/abstract_members.dart
@@ -55,4 +55,44 @@
noSuchMethod(_);
}
+class C {
+ void interfaceMethod1(_) {}
+}
+
+// This class should have an error, the method C.interfaceMethod1 conflicts
+// with the field Interface2.interfaceMethod1.
+abstract class D extends C implements Interface2 {}
+
+class E {
+ void set interfaceMethod1(_) {}
+}
+
+// This class should have an error, the setter E.interfaceMethod1 conflicts
+// with the method Interface1.interfaceMethod1.
+abstract class F extends E implements Interface1 {}
+
+class Foo {
+ void foo() {}
+}
+
+class G {
+ void set foo(_) {}
+}
+
+// This class should have an error, the setter G.foo conflicts with the method
+// Foo.foo.
+abstract class H extends G implements Foo {}
+
+class Bar {
+ Object get foo => null;
+}
+
+class I {
+ Object foo() {}
+}
+
+// This class should have an error, the getter Bar.foo conflicts with the
+// method I.foo.
+abstract class J extends I implements Bar {}
+
main() {}
diff --git a/pkg/front_end/testcases/abstract_members.dart.legacy.expect b/pkg/front_end/testcases/abstract_members.dart.legacy.expect
index 0c85dd2..dd5cc31 100644
--- a/pkg/front_end/testcases/abstract_members.dart.legacy.expect
+++ b/pkg/front_end/testcases/abstract_members.dart.legacy.expect
@@ -89,6 +89,26 @@
// pkg/front_end/testcases/abstract_members.dart:16:8: Context: 'Interface3.interfaceMethod3' is defined here.
// void interfaceMethod3() {}
// ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/abstract_members.dart:64:16: Error: Can't inherit members that conflict with each other.
+// abstract class D extends C implements Interface2 {}
+// ^
+// pkg/front_end/testcases/abstract_members.dart:59:8: Context: This is one inherited member.
+// void interfaceMethod1(_) {}
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:12:7: Context: This is the other inherited member.
+// var interfaceMethod1;
+// ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/abstract_members.dart:96:16: Error: Can't inherit members that conflict with each other.
+// abstract class J extends I implements Bar {}
+// ^
+// pkg/front_end/testcases/abstract_members.dart:91:10: Context: This is one inherited member.
+// Object foo() {}
+// ^^^
+// pkg/front_end/testcases/abstract_members.dart:87:14: Context: This is the other inherited member.
+// Object get foo => null;
+// ^^^
// Unhandled errors:
//
@@ -130,6 +150,14 @@
//
// class MyMock3 extends B {
// ^^^^^^^
+//
+// pkg/front_end/testcases/abstract_members.dart:64:16: Error: Can't inherit members that conflict with each other.
+// abstract class D extends C implements Interface2 {}
+// ^
+//
+// pkg/front_end/testcases/abstract_members.dart:96:16: Error: Can't inherit members that conflict with each other.
+// abstract class J extends I implements Bar {}
+// ^
library;
import self as self;
@@ -235,4 +263,61 @@
no-such-method-forwarder set property2(dynamic _) → void
return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#property2=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
}
+class C extends core::Object {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ method interfaceMethod1(dynamic _) → void {}
+}
+abstract class D extends self::C implements self::Interface2 {
+ synthetic constructor •() → self::D
+ : super self::C::•()
+ ;
+}
+class E extends core::Object {
+ synthetic constructor •() → self::E
+ : super core::Object::•()
+ ;
+ set interfaceMethod1(dynamic _) → void {}
+}
+abstract class F extends self::E implements self::Interface1 {
+ synthetic constructor •() → self::F
+ : super self::E::•()
+ ;
+}
+class Foo extends core::Object {
+ synthetic constructor •() → self::Foo
+ : super core::Object::•()
+ ;
+ method foo() → void {}
+}
+class G extends core::Object {
+ synthetic constructor •() → self::G
+ : super core::Object::•()
+ ;
+ set foo(dynamic _) → void {}
+}
+abstract class H extends self::G implements self::Foo {
+ synthetic constructor •() → self::H
+ : super self::G::•()
+ ;
+}
+class Bar extends core::Object {
+ synthetic constructor •() → self::Bar
+ : super core::Object::•()
+ ;
+ get foo() → core::Object
+ return null;
+}
+class I extends core::Object {
+ synthetic constructor •() → self::I
+ : super core::Object::•()
+ ;
+ method foo() → core::Object {}
+}
+abstract class J extends self::I implements self::Bar {
+ synthetic constructor •() → self::J
+ : super self::I::•()
+ ;
+}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/abstract_members.dart.legacy.transformed.expect b/pkg/front_end/testcases/abstract_members.dart.legacy.transformed.expect
index 7e489f3..22ee2e5 100644
--- a/pkg/front_end/testcases/abstract_members.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/abstract_members.dart.legacy.transformed.expect
@@ -38,6 +38,14 @@
//
// class MyMock3 extends B {
// ^^^^^^^
+//
+// pkg/front_end/testcases/abstract_members.dart:64:16: Error: Can't inherit members that conflict with each other.
+// abstract class D extends C implements Interface2 {}
+// ^
+//
+// pkg/front_end/testcases/abstract_members.dart:96:16: Error: Can't inherit members that conflict with each other.
+// abstract class J extends I implements Bar {}
+// ^
library;
import self as self;
@@ -143,4 +151,61 @@
no-such-method-forwarder set property2(dynamic _) → void
return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#property2=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
}
+class C extends core::Object {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ method interfaceMethod1(dynamic _) → void {}
+}
+abstract class D extends self::C implements self::Interface2 {
+ synthetic constructor •() → self::D
+ : super self::C::•()
+ ;
+}
+class E extends core::Object {
+ synthetic constructor •() → self::E
+ : super core::Object::•()
+ ;
+ set interfaceMethod1(dynamic _) → void {}
+}
+abstract class F extends self::E implements self::Interface1 {
+ synthetic constructor •() → self::F
+ : super self::E::•()
+ ;
+}
+class Foo extends core::Object {
+ synthetic constructor •() → self::Foo
+ : super core::Object::•()
+ ;
+ method foo() → void {}
+}
+class G extends core::Object {
+ synthetic constructor •() → self::G
+ : super core::Object::•()
+ ;
+ set foo(dynamic _) → void {}
+}
+abstract class H extends self::G implements self::Foo {
+ synthetic constructor •() → self::H
+ : super self::G::•()
+ ;
+}
+class Bar extends core::Object {
+ synthetic constructor •() → self::Bar
+ : super core::Object::•()
+ ;
+ get foo() → core::Object
+ return null;
+}
+class I extends core::Object {
+ synthetic constructor •() → self::I
+ : super core::Object::•()
+ ;
+ method foo() → core::Object {}
+}
+abstract class J extends self::I implements self::Bar {
+ synthetic constructor •() → self::J
+ : super self::I::•()
+ ;
+}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/abstract_members.dart.outline.expect b/pkg/front_end/testcases/abstract_members.dart.outline.expect
index e2bf105..a352fbd 100644
--- a/pkg/front_end/testcases/abstract_members.dart.outline.expect
+++ b/pkg/front_end/testcases/abstract_members.dart.outline.expect
@@ -89,6 +89,26 @@
// pkg/front_end/testcases/abstract_members.dart:16:8: Context: 'Interface3.interfaceMethod3' is defined here.
// void interfaceMethod3() {}
// ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/abstract_members.dart:64:16: Error: Can't inherit members that conflict with each other.
+// abstract class D extends C implements Interface2 {}
+// ^
+// pkg/front_end/testcases/abstract_members.dart:59:8: Context: This is one inherited member.
+// void interfaceMethod1(_) {}
+// ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:12:7: Context: This is the other inherited member.
+// var interfaceMethod1;
+// ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/abstract_members.dart:96:16: Error: Can't inherit members that conflict with each other.
+// abstract class J extends I implements Bar {}
+// ^
+// pkg/front_end/testcases/abstract_members.dart:91:10: Context: This is one inherited member.
+// Object foo() {}
+// ^^^
+// pkg/front_end/testcases/abstract_members.dart:87:14: Context: This is the other inherited member.
+// Object get foo => null;
+// ^^^
library;
import self as self;
@@ -195,5 +215,57 @@
no-such-method-forwarder set property2(dynamic _) → void
return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#property2=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
}
+class C extends core::Object {
+ synthetic constructor •() → self::C
+ ;
+ method interfaceMethod1(dynamic _) → void
+ ;
+}
+abstract class D extends self::C implements self::Interface2 {
+ synthetic constructor •() → self::D
+ ;
+}
+class E extends core::Object {
+ synthetic constructor •() → self::E
+ ;
+ set interfaceMethod1(dynamic _) → void
+ ;
+}
+abstract class F extends self::E implements self::Interface1 {
+ synthetic constructor •() → self::F
+ ;
+}
+class Foo extends core::Object {
+ synthetic constructor •() → self::Foo
+ ;
+ method foo() → void
+ ;
+}
+class G extends core::Object {
+ synthetic constructor •() → self::G
+ ;
+ set foo(dynamic _) → void
+ ;
+}
+abstract class H extends self::G implements self::Foo {
+ synthetic constructor •() → self::H
+ ;
+}
+class Bar extends core::Object {
+ synthetic constructor •() → self::Bar
+ ;
+ get foo() → core::Object
+ ;
+}
+class I extends core::Object {
+ synthetic constructor •() → self::I
+ ;
+ method foo() → core::Object
+ ;
+}
+abstract class J extends self::I implements self::Bar {
+ synthetic constructor •() → self::J
+ ;
+}
static method main() → dynamic
;
diff --git a/pkg/front_end/testcases/abstract_members.dart.strong.expect b/pkg/front_end/testcases/abstract_members.dart.strong.expect
index c568386..65ea5ee 100644
--- a/pkg/front_end/testcases/abstract_members.dart.strong.expect
+++ b/pkg/front_end/testcases/abstract_members.dart.strong.expect
@@ -10,6 +10,46 @@
// var interfaceMethod1;
// ^
//
+// pkg/front_end/testcases/abstract_members.dart:64:16: Error: Can't inherit members that conflict with each other.
+// abstract class D extends C implements Interface2 {}
+// ^
+// pkg/front_end/testcases/abstract_members.dart:59:8: Context: This is one inherited member.
+// void interfaceMethod1(_) {}
+// ^
+// pkg/front_end/testcases/abstract_members.dart:12:7: Context: This is the other inherited member.
+// var interfaceMethod1;
+// ^
+//
+// pkg/front_end/testcases/abstract_members.dart:72:16: Error: Can't inherit members that conflict with each other.
+// abstract class F extends E implements Interface1 {}
+// ^
+// pkg/front_end/testcases/abstract_members.dart:6:8: Context: This is one inherited member.
+// void interfaceMethod1() {}
+// ^
+// pkg/front_end/testcases/abstract_members.dart:67:12: Context: This is the other inherited member.
+// void set interfaceMethod1(_) {}
+// ^
+//
+// pkg/front_end/testcases/abstract_members.dart:84:16: Error: Can't inherit members that conflict with each other.
+// abstract class H extends G implements Foo {}
+// ^
+// pkg/front_end/testcases/abstract_members.dart:75:8: Context: This is one inherited member.
+// void foo() {}
+// ^
+// pkg/front_end/testcases/abstract_members.dart:79:12: Context: This is the other inherited member.
+// void set foo(_) {}
+// ^
+//
+// pkg/front_end/testcases/abstract_members.dart:96:16: Error: Can't inherit members that conflict with each other.
+// abstract class J extends I implements Bar {}
+// ^
+// pkg/front_end/testcases/abstract_members.dart:91:10: Context: This is one inherited member.
+// Object foo() {}
+// ^
+// pkg/front_end/testcases/abstract_members.dart:87:14: Context: This is the other inherited member.
+// Object get foo => null;
+// ^
+//
// pkg/front_end/testcases/abstract_members.dart:33:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
// - 'interfaceMethod2'
// - 'abstractMethod'
@@ -104,6 +144,22 @@
// abstract class A implements Interface1, Interface2, Interface3 {
// ^
//
+// pkg/front_end/testcases/abstract_members.dart:64:16: Error: Can't inherit members that conflict with each other.
+// abstract class D extends C implements Interface2 {}
+// ^
+//
+// pkg/front_end/testcases/abstract_members.dart:72:16: Error: Can't inherit members that conflict with each other.
+// abstract class F extends E implements Interface1 {}
+// ^
+//
+// pkg/front_end/testcases/abstract_members.dart:84:16: Error: Can't inherit members that conflict with each other.
+// abstract class H extends G implements Foo {}
+// ^
+//
+// pkg/front_end/testcases/abstract_members.dart:96:16: Error: Can't inherit members that conflict with each other.
+// abstract class J extends I implements Bar {}
+// ^
+//
// pkg/front_end/testcases/abstract_members.dart:33:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
// - 'interfaceMethod2'
// - 'abstractMethod'
@@ -245,4 +301,61 @@
no-such-method-forwarder set property2(dynamic _) → void
return this.{self::MyMock3::noSuchMethod}(new core::_InvocationMirror::_withType(#property2=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
}
+class C extends core::Object {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ method interfaceMethod1(dynamic _) → void {}
+}
+abstract class D extends self::C implements self::Interface2 {
+ synthetic constructor •() → self::D
+ : super self::C::•()
+ ;
+}
+class E extends core::Object {
+ synthetic constructor •() → self::E
+ : super core::Object::•()
+ ;
+ set interfaceMethod1(dynamic _) → void {}
+}
+abstract class F extends self::E implements self::Interface1 {
+ synthetic constructor •() → self::F
+ : super self::E::•()
+ ;
+}
+class Foo extends core::Object {
+ synthetic constructor •() → self::Foo
+ : super core::Object::•()
+ ;
+ method foo() → void {}
+}
+class G extends core::Object {
+ synthetic constructor •() → self::G
+ : super core::Object::•()
+ ;
+ set foo(dynamic _) → void {}
+}
+abstract class H extends self::G implements self::Foo {
+ synthetic constructor •() → self::H
+ : super self::G::•()
+ ;
+}
+class Bar extends core::Object {
+ synthetic constructor •() → self::Bar
+ : super core::Object::•()
+ ;
+ get foo() → core::Object
+ return null;
+}
+class I extends core::Object {
+ synthetic constructor •() → self::I
+ : super core::Object::•()
+ ;
+ method foo() → core::Object {}
+}
+abstract class J extends self::I implements self::Bar {
+ synthetic constructor •() → self::J
+ : super self::I::•()
+ ;
+}
static method main() → dynamic {}