Merge interfaces when building hierarchy

Change-Id: I2d3db2fa653a4caa9f90bdc8557d80f5a2836a52
Reviewed-on: https://dart-review.googlesource.com/c/87641
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index c736ea0..bfea29e 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -4525,7 +4525,6 @@
 const MessageCode messageInheritedMembersConflict = const MessageCode(
     "InheritedMembersConflict",
     analyzerCodes: <String>["CONFLICTS_WITH_INHERITED_MEMBER"],
-    severity: Severity.errorLegacyWarning,
     message: r"""Can't inherit members that conflict with each other.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
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 5f7447c..6dc9be2 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
@@ -14,6 +14,9 @@
         LocatedMessage,
         messageDeclaredMemberConflictsWithInheritedMember,
         messageDeclaredMemberConflictsWithInheritedMemberCause,
+        messageInheritedMembersConflict,
+        messageInheritedMembersConflictCause1,
+        messageInheritedMembersConflictCause2,
         templateMissingImplementationCause,
         templateMissingImplementationNotAbstract;
 
@@ -54,7 +57,8 @@
 
   ClassHierarchyBuilder(this.objectClass);
 
-  Declaration handleOverride(Declaration member, Declaration superMember) {
+  Declaration handleOverride(KernelClassBuilder cls, Declaration member,
+      Declaration superMember, bool isMergingInterfaces) {
     if (member.next != null || superMember.next != null) {
       // Don't check overrides involving duplicated members.
       return member;
@@ -64,19 +68,32 @@
     if ((memberKind(target) ?? ProcedureKind.Getter) !=
         (memberKind(superTarget) ?? ProcedureKind.Getter)) {
       String name = member.fullNameForErrors;
-      KernelClassBuilder cls = member.parent;
-      cls.addProblem(messageDeclaredMemberConflictsWithInheritedMember,
-          member.charOffset, name.length,
-          context: <LocatedMessage>[
-            messageDeclaredMemberConflictsWithInheritedMemberCause.withLocation(
-                superMember.fileUri, superMember.charOffset, name.length)
-          ]);
+      if (isMergingInterfaces) {
+        cls.addProblem(messageInheritedMembersConflict, cls.charOffset,
+            cls.fullNameForErrors.length,
+            context: <LocatedMessage>[
+              messageInheritedMembersConflictCause1.withLocation(
+                  member.fileUri, member.charOffset, name.length),
+              messageInheritedMembersConflictCause2.withLocation(
+                  superMember.fileUri, superMember.charOffset, name.length),
+            ]);
+      } else {
+        cls.addProblem(messageDeclaredMemberConflictsWithInheritedMember,
+            member.charOffset, name.length,
+            context: <LocatedMessage>[
+              messageDeclaredMemberConflictsWithInheritedMemberCause
+                  .withLocation(
+                      superMember.fileUri, superMember.charOffset, name.length)
+            ]);
+      }
     }
     if (target.name == noSuchMethodName && !target.isAbstract) {
       hasNoSuchMethod = true;
     }
     Declaration result = member;
-    if (target.isAbstract) {
+    if (isMergingInterfaces) {
+      // TODO(ahe): Combine the signatures of member and superMember.
+    } else if (target.isAbstract) {
       if (!superTarget.isAbstract) {
         // An abstract method doesn't override an implemention inherited from a
         // superclass.
@@ -88,16 +105,17 @@
     return result;
   }
 
-  void handleNewMember(Declaration member) {
+  void handleNewMember(Declaration member, bool isMergingInterfaces) {
     Member target = member.target;
-    if (target.isAbstract) {
+    if (!isMergingInterfaces && target.isAbstract) {
       abstractMemberCount++;
     }
   }
 
-  void handleInheritance(KernelClassBuilder cls, Declaration member) {
+  void handleInheritance(
+      KernelClassBuilder cls, Declaration member, bool isMergingInterfaces) {
     Member target = member.target;
-    if (target.isAbstract) {
+    if (!isMergingInterfaces && target.isAbstract) {
       if (isNameVisibleIn(target.name, cls.library)) {
         abstractMemberCount++;
       }
@@ -143,16 +161,29 @@
           ..sort(compareDeclarations);
     List<Declaration> allMembers;
     List<Declaration> allSetters;
+    List<Declaration> interfaceMembers;
+    List<Declaration> interfaceSetters;
     if (supernode == null) {
       // This should be Object.
-      allMembers = sortedLocals;
-      allSetters = sortedSetters;
+      interfaceMembers = allMembers = sortedLocals;
+      interfaceSetters = allSetters = sortedSetters;
     } else {
-      allMembers = merge(cls, sortedLocals, supernode.classMembers);
-      allSetters = merge(cls, sortedSetters, supernode.classSetters);
+      allMembers = merge(cls, sortedLocals, supernode.classMembers, false);
+      allSetters = merge(cls, sortedSetters, supernode.classSetters, false);
+      List<KernelTypeBuilder> interfaces = cls.interfaces;
+      if (interfaces != null) {
+        MergeResult result = mergeInterfaces(cls, supernode, interfaces);
+        interfaceMembers = result.mergedMembers;
+        interfaceSetters = result.mergedSetters;
+      } else {
+        interfaceMembers = allMembers;
+        interfaceSetters = allSetters;
+      }
     }
-    nodes[cls] = new ClassHierarchyNode(cls, scope, allMembers, allSetters);
+    nodes[cls] = new ClassHierarchyNode(
+        cls, scope, allMembers, allSetters, interfaceMembers, interfaceSetters);
     mergeAccessors(cls, allMembers, allSetters);
+
     if (abstractMemberCount != 0 && !cls.isAbstract) {
       if (!hasNoSuchMethod) {
         reportMissingMembers(cls, allMembers, allSetters);
@@ -163,6 +194,46 @@
     abstractMemberCount = 0;
   }
 
+  MergeResult mergeInterfaces(KernelClassBuilder cls,
+      ClassHierarchyNode supernode, List<KernelTypeBuilder> interfaces) {
+    List<List<Declaration>> memberLists =
+        List<List<Declaration>>(interfaces.length + 1);
+    List<List<Declaration>> setterLists =
+        List<List<Declaration>>(interfaces.length + 1);
+    memberLists[0] = supernode.interfaceMembers;
+    setterLists[0] = supernode.interfaceSetters;
+    for (int i = 0; i < interfaces.length; i++) {
+      ClassHierarchyNode interfaceNode = getNode(interfaces[i]);
+      if (interfaceNode == null) {
+        memberLists[i + 1] = <Declaration>[];
+        setterLists[i + 1] = <Declaration>[];
+      } else {
+        memberLists[i + 1] = interfaceNode.interfaceMembers;
+        setterLists[i + 1] = interfaceNode.interfaceSetters;
+      }
+    }
+    return new MergeResult(
+        mergeLists(cls, memberLists), mergeLists(cls, setterLists));
+  }
+
+  List<Declaration> mergeLists(
+      KernelClassBuilder cls, List<List<Declaration>> input) {
+    // This is a k-way merge sort (where k is `interfaces.length + 1`). We
+    // merge the lists pairwise, which reduces the number of lists to merge by
+    // half on each iteration. Consequently, we perform O(log k) merges.
+    while (input.length > 1) {
+      List<List<Declaration>> output = <List<Declaration>>[];
+      for (int i = 0; i < input.length - 1; i += 2) {
+        output.add(merge(cls, input[i], input[i + 1], true));
+      }
+      if (input.length.isOdd) {
+        output.add(input.last);
+      }
+      input = output;
+    }
+    return input.single;
+  }
+
   /// Merge [and check] accessors. This entails removing setters corresponding
   /// to fields, and checking that setters don't override regular methods.
   void mergeAccessors(KernelClassBuilder cls, List<Declaration> allMembers,
@@ -284,8 +355,11 @@
     return type is KernelNamedTypeBuilder ? type.declaration : null;
   }
 
-  List<Declaration> merge(KernelClassBuilder cls,
-      List<Declaration> localMembers, List<Declaration> superMembers) {
+  List<Declaration> merge(
+      KernelClassBuilder cls,
+      List<Declaration> localMembers,
+      List<Declaration> superMembers,
+      bool isMergingInterfaces) {
     final List<Declaration> mergedMembers = new List<Declaration>.filled(
         localMembers.length + superMembers.length, null,
         growable: true);
@@ -300,28 +374,28 @@
       final int compare = compareDeclarations(localMember, superMember);
       if (compare == 0) {
         mergedMembers[mergedMemberCount++] =
-            handleOverride(localMember, superMember);
+            handleOverride(cls, localMember, superMember, isMergingInterfaces);
         i++;
         j++;
       } else if (compare < 0) {
-        handleNewMember(localMember);
+        handleNewMember(localMember, isMergingInterfaces);
         mergedMembers[mergedMemberCount++] = localMember;
         i++;
       } else {
-        handleInheritance(cls, superMember);
+        handleInheritance(cls, superMember, isMergingInterfaces);
         mergedMembers[mergedMemberCount++] = superMember;
         j++;
       }
     }
     while (i < localMembers.length) {
       final Declaration localMember = localMembers[i];
-      handleNewMember(localMember);
+      handleNewMember(localMember, isMergingInterfaces);
       mergedMembers[mergedMemberCount++] = localMember;
       i++;
     }
     while (j < superMembers.length) {
       final Declaration superMember = superMembers[j];
-      handleInheritance(cls, superMember);
+      handleInheritance(cls, superMember, isMergingInterfaces);
       mergedMembers[mergedMemberCount++] = superMember;
       j++;
     }
@@ -344,8 +418,27 @@
   /// superclasses. The members are sorted by [compareDeclarations].
   final List<Declaration> classMembers;
 
+  /// Similar to [classMembers] but for setters.
   final List<Declaration> classSetters;
 
-  ClassHierarchyNode(
-      this.cls, this.localMembers, this.classMembers, this.classSetters);
+  /// All the interface members of this class including [interfaceMembers] of
+  /// its supertypes. The members are sorted by [compareDeclarations].
+  ///
+  /// In addition to the members of [classMembers] this also contains members
+  /// from interfaces.
+  final List<Declaration> interfaceMembers;
+
+  /// Similar to [interfaceMembers] but for setters.
+  final List<Declaration> interfaceSetters;
+
+  ClassHierarchyNode(this.cls, this.localMembers, this.classMembers,
+      this.classSetters, this.interfaceMembers, this.interfaceSetters);
+}
+
+class MergeResult {
+  final List<Declaration> mergedMembers;
+
+  final List<Declaration> mergedSetters;
+
+  MergeResult(this.mergedMembers, this.mergedSetters);
 }
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 76bf2d7..eb90f60 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -1947,7 +1947,6 @@
 
 InheritedMembersConflict:
   template: "Can't inherit members that conflict with each other."
-  severity: ERROR_LEGACY_WARNING
   analyzerCode: CONFLICTS_WITH_INHERITED_MEMBER
   script:
     - >-
diff --git a/pkg/front_end/testcases/abstract_members.dart b/pkg/front_end/testcases/abstract_members.dart
index 82347d4..00f4f14 100644
--- a/pkg/front_end/testcases/abstract_members.dart
+++ b/pkg/front_end/testcases/abstract_members.dart
@@ -2,7 +2,21 @@
 // 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.
 
-abstract class A {
+class Interface1 {
+  void interfaceMethod1() {}
+}
+
+class Interface2 {
+  void interfaceMethod2() {}
+
+  var interfaceMethod1;
+}
+
+class Interface3 {
+  void interfaceMethod3() {}
+}
+
+abstract class A implements Interface1, Interface2, Interface3 {
   aMethod() {}
   abstractMethod();
   void set property1(_);
diff --git a/pkg/front_end/testcases/abstract_members.dart.legacy.expect b/pkg/front_end/testcases/abstract_members.dart.legacy.expect
index 15f50c7..3ac995d 100644
--- a/pkg/front_end/testcases/abstract_members.dart.legacy.expect
+++ b/pkg/front_end/testcases/abstract_members.dart.legacy.expect
@@ -1,6 +1,16 @@
 // Formatted problems:
 //
-// pkg/front_end/testcases/abstract_members.dart:19:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
+// pkg/front_end/testcases/abstract_members.dart:19:16: Error: Can't inherit members that conflict with each other.
+// abstract class A implements Interface1, Interface2, Interface3 {
+//                ^
+// pkg/front_end/testcases/abstract_members.dart:6: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:33:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
 //  - A.abstractMethod
 //  - A.property3=
 //  - A.property1=
@@ -12,19 +22,23 @@
 //
 // class MyClass extends B {
 //       ^^^^^^^
-// pkg/front_end/testcases/abstract_members.dart:7:3: Context: 'A.abstractMethod' is defined here.
+// pkg/front_end/testcases/abstract_members.dart:21:3: Context: 'A.abstractMethod' is defined here.
 //   abstractMethod();
 //   ^^^^^^^^^^^^^^
-// pkg/front_end/testcases/abstract_members.dart:10:12: Context: 'A.property3=' is defined here.
+// pkg/front_end/testcases/abstract_members.dart:24:12: Context: 'A.property3=' is defined here.
 //   void set property3(_);
 //            ^^^^^^^^^
-// pkg/front_end/testcases/abstract_members.dart:8:12: Context: 'A.property1=' is defined here.
+// pkg/front_end/testcases/abstract_members.dart:22:12: Context: 'A.property1=' is defined here.
 //   void set property1(_);
 //            ^^^^^^^^^
 
 // Unhandled errors:
 //
-// pkg/front_end/testcases/abstract_members.dart:19:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
+// pkg/front_end/testcases/abstract_members.dart:19:16: Error: Can't inherit members that conflict with each other.
+// abstract class A implements Interface1, Interface2, Interface3 {
+//                ^
+//
+// pkg/front_end/testcases/abstract_members.dart:33:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
 //  - A.abstractMethod
 //  - A.property3=
 //  - A.property1=
@@ -41,7 +55,26 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class A extends core::Object {
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  method interfaceMethod1() → void {}
+}
+class Interface2 extends core::Object {
+  field dynamic interfaceMethod1 = null;
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  method interfaceMethod2() → void {}
+}
+class Interface3 extends core::Object {
+  synthetic constructor •() → self::Interface3
+    : super core::Object::•()
+    ;
+  method interfaceMethod3() → void {}
+}
+abstract class A extends core::Object implements self::Interface1, self::Interface2, self::Interface3 {
   synthetic constructor •() → self::A
     : super core::Object::•()
     ;
@@ -68,8 +101,12 @@
   method aMethod() → dynamic {}
   method bMethod() → dynamic {}
   method cMethod() → dynamic {}
+  no-such-method-forwarder get interfaceMethod1() → dynamic
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1, 1, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))) as{TypeError} dynamic;
   no-such-method-forwarder set property3(dynamic _) → void
     return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#property3=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  no-such-method-forwarder set interfaceMethod1(dynamic value) → void
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
   no-such-method-forwarder set property1(dynamic _) → void
     return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#property1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, 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 ea90b55..1e1ebac 100644
--- a/pkg/front_end/testcases/abstract_members.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/abstract_members.dart.legacy.transformed.expect
@@ -1,6 +1,10 @@
 // Unhandled errors:
 //
-// pkg/front_end/testcases/abstract_members.dart:19:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
+// pkg/front_end/testcases/abstract_members.dart:19:16: Error: Can't inherit members that conflict with each other.
+// abstract class A implements Interface1, Interface2, Interface3 {
+//                ^
+//
+// pkg/front_end/testcases/abstract_members.dart:33:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
 //  - A.abstractMethod
 //  - A.property3=
 //  - A.property1=
@@ -17,7 +21,26 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class A extends core::Object {
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  method interfaceMethod1() → void {}
+}
+class Interface2 extends core::Object {
+  field dynamic interfaceMethod1 = null;
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  method interfaceMethod2() → void {}
+}
+class Interface3 extends core::Object {
+  synthetic constructor •() → self::Interface3
+    : super core::Object::•()
+    ;
+  method interfaceMethod3() → void {}
+}
+abstract class A extends core::Object implements self::Interface1, self::Interface2, self::Interface3 {
   synthetic constructor •() → self::A
     : super core::Object::•()
     ;
@@ -44,8 +67,12 @@
   method aMethod() → dynamic {}
   method bMethod() → dynamic {}
   method cMethod() → dynamic {}
+  no-such-method-forwarder get interfaceMethod1() → dynamic
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1, 1, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))) as{TypeError} dynamic;
   no-such-method-forwarder set property3(dynamic _) → void
     return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#property3=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  no-such-method-forwarder set interfaceMethod1(dynamic value) → void
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
   no-such-method-forwarder set property1(dynamic _) → void
     return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#property1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
 }
diff --git a/pkg/front_end/testcases/abstract_members.dart.outline.expect b/pkg/front_end/testcases/abstract_members.dart.outline.expect
index 93b459c..1c95548 100644
--- a/pkg/front_end/testcases/abstract_members.dart.outline.expect
+++ b/pkg/front_end/testcases/abstract_members.dart.outline.expect
@@ -1,6 +1,16 @@
 // Formatted problems:
 //
-// pkg/front_end/testcases/abstract_members.dart:19:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
+// pkg/front_end/testcases/abstract_members.dart:19:16: Error: Can't inherit members that conflict with each other.
+// abstract class A implements Interface1, Interface2, Interface3 {
+//                ^
+// pkg/front_end/testcases/abstract_members.dart:6: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:33:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
 //  - A.abstractMethod
 //  - A.property3=
 //  - A.property1=
@@ -12,13 +22,13 @@
 //
 // class MyClass extends B {
 //       ^^^^^^^
-// pkg/front_end/testcases/abstract_members.dart:7:3: Context: 'A.abstractMethod' is defined here.
+// pkg/front_end/testcases/abstract_members.dart:21:3: Context: 'A.abstractMethod' is defined here.
 //   abstractMethod();
 //   ^^^^^^^^^^^^^^
-// pkg/front_end/testcases/abstract_members.dart:10:12: Context: 'A.property3=' is defined here.
+// pkg/front_end/testcases/abstract_members.dart:24:12: Context: 'A.property3=' is defined here.
 //   void set property3(_);
 //            ^^^^^^^^^
-// pkg/front_end/testcases/abstract_members.dart:8:12: Context: 'A.property1=' is defined here.
+// pkg/front_end/testcases/abstract_members.dart:22:12: Context: 'A.property1=' is defined here.
 //   void set property1(_);
 //            ^^^^^^^^^
 
@@ -26,7 +36,26 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class A extends core::Object {
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    ;
+  method interfaceMethod1() → void
+    ;
+}
+class Interface2 extends core::Object {
+  field dynamic interfaceMethod1;
+  synthetic constructor •() → self::Interface2
+    ;
+  method interfaceMethod2() → void
+    ;
+}
+class Interface3 extends core::Object {
+  synthetic constructor •() → self::Interface3
+    ;
+  method interfaceMethod3() → void
+    ;
+}
+abstract class A extends core::Object implements self::Interface1, self::Interface2, self::Interface3 {
   synthetic constructor •() → self::A
     ;
   method aMethod() → dynamic
@@ -57,8 +86,12 @@
     ;
   method cMethod() → dynamic
     ;
+  no-such-method-forwarder get interfaceMethod1() → dynamic
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1, 1, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))) as{TypeError} dynamic;
   no-such-method-forwarder set property3(dynamic _) → void
     return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#property3=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  no-such-method-forwarder set interfaceMethod1(dynamic value) → void
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
   no-such-method-forwarder set property1(dynamic _) → void
     return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#property1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
 }
diff --git a/pkg/front_end/testcases/abstract_members.dart.strong.expect b/pkg/front_end/testcases/abstract_members.dart.strong.expect
index 9067a7e..81ff760 100644
--- a/pkg/front_end/testcases/abstract_members.dart.strong.expect
+++ b/pkg/front_end/testcases/abstract_members.dart.strong.expect
@@ -1,8 +1,23 @@
 // Formatted problems:
 //
-// pkg/front_end/testcases/abstract_members.dart:19:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
+// pkg/front_end/testcases/abstract_members.dart:19:16: Error: Can't inherit members that conflict with each other.
+// abstract class A implements Interface1, Interface2, Interface3 {
+//                ^
+// pkg/front_end/testcases/abstract_members.dart:6: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:33:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
+//  - 'interfaceMethod2'
 //  - 'abstractMethod'
+//  - 'interfaceMethod1'
+//  - 'interfaceMethod1'
+//  - 'interfaceMethod3'
 //  - 'property3='
+//  - 'interfaceMethod1='
 //  - 'property1='
 // Try to either
 //  - provide an implementation,
@@ -12,21 +27,45 @@
 //
 // class MyClass extends B {
 //       ^^^^^^^
-// pkg/front_end/testcases/abstract_members.dart:7:3: Context: 'abstractMethod' is defined here.
+// pkg/front_end/testcases/abstract_members.dart:10:8: Context: 'interfaceMethod2' is defined here.
+//   void interfaceMethod2() {}
+//        ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:21:3: Context: 'abstractMethod' is defined here.
 //   abstractMethod();
 //   ^^^^^^^^^^^^^^
-// pkg/front_end/testcases/abstract_members.dart:10:12: Context: 'property3=' is defined here.
+// pkg/front_end/testcases/abstract_members.dart:6:8: Context: 'interfaceMethod1' is defined here.
+//   void interfaceMethod1() {}
+//        ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:12:7: Context: 'interfaceMethod1' is defined here.
+//   var interfaceMethod1;
+//       ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:16:8: Context: 'interfaceMethod3' is defined here.
+//   void interfaceMethod3() {}
+//        ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:24:12: Context: 'property3=' is defined here.
 //   void set property3(_);
 //            ^^^^^^^^^
-// pkg/front_end/testcases/abstract_members.dart:8:12: Context: 'property1=' is defined here.
+// pkg/front_end/testcases/abstract_members.dart:12:7: Context: 'interfaceMethod1=' is defined here.
+//   var interfaceMethod1;
+//       ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/abstract_members.dart:22:12: Context: 'property1=' is defined here.
 //   void set property1(_);
 //            ^^^^^^^^^
 
 // Unhandled errors:
 //
-// pkg/front_end/testcases/abstract_members.dart:19:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
+// pkg/front_end/testcases/abstract_members.dart:19:16: Error: Can't inherit members that conflict with each other.
+// abstract class A implements Interface1, Interface2, Interface3 {
+//                ^
+//
+// pkg/front_end/testcases/abstract_members.dart:33:7: Error: The non-abstract class 'MyClass' is missing implementations for these members:
+//  - 'interfaceMethod2'
 //  - 'abstractMethod'
+//  - 'interfaceMethod1'
+//  - 'interfaceMethod1'
+//  - 'interfaceMethod3'
 //  - 'property3='
+//  - 'interfaceMethod1='
 //  - 'property1='
 // Try to either
 //  - provide an implementation,
@@ -41,7 +80,26 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class A extends core::Object {
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1
+    : super core::Object::•()
+    ;
+  method interfaceMethod1() → void {}
+}
+class Interface2 extends core::Object {
+  field dynamic interfaceMethod1 = null;
+  synthetic constructor •() → self::Interface2
+    : super core::Object::•()
+    ;
+  method interfaceMethod2() → void {}
+}
+class Interface3 extends core::Object {
+  synthetic constructor •() → self::Interface3
+    : super core::Object::•()
+    ;
+  method interfaceMethod3() → void {}
+}
+abstract class A extends core::Object implements self::Interface1, self::Interface2, self::Interface3 {
   synthetic constructor •() → self::A
     : super core::Object::•()
     ;
@@ -68,8 +126,12 @@
   method aMethod() → dynamic {}
   method bMethod() → dynamic {}
   method cMethod() → dynamic {}
+  no-such-method-forwarder get interfaceMethod1() → dynamic
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1, 1, const <core::Type>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{}))) as{TypeError} dynamic;
   no-such-method-forwarder set property3(dynamic _) → void
     return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#property3=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
+  no-such-method-forwarder set interfaceMethod1(dynamic value) → void
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#interfaceMethod1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
   no-such-method-forwarder set property1(dynamic _) → void
     return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#property1=, 2, const <core::Type>[], core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol, dynamic>(const <core::Symbol, dynamic>{})));
 }
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 92b5ce5..20f95d6 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -6,6 +6,7 @@
 # Kernel ASTs directly, that is, code in pkg/fasta/lib/src/kernel/ with
 # strong-mode enabled.
 
+abstract_members: TypeCheckError
 accessors: RuntimeError
 ambiguous_exports: RuntimeError # Expected, this file exports two main methods.
 argument_mismatch: InstrumentationMismatch # Test assumes Dart 1.0 semantics
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 5e30091..94e38cd 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -6,6 +6,7 @@
 # the round trip for Kernel textual serialization where the initial binary
 # Kernel files are produced by compiling Dart code via Fasta.
 
+abstract_members: TypeCheckError
 accessors: RuntimeError
 ambiguous_exports: RuntimeError # Expected, this file exports two main methods.
 argument_mismatch: InstrumentationMismatch # Test assumes Dart 1.0 semantics