[cfe] Preclude inherited members

This updates the handling of method/setter conflict between declared
and inherited members in extension types. Declared member now precludes
the conflicting members from being inherited, thus avoid the compile
time error.

Closes #53720

Change-Id: Ie185fa5f378d3bca64ebf77480e2fcefa767bc30
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/341560
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/lib/src/fasta/kernel/hierarchy/extension_type_members.dart b/pkg/front_end/lib/src/fasta/kernel/hierarchy/extension_type_members.dart
index 5e5c930..60b6ccb 100644
--- a/pkg/front_end/lib/src/fasta/kernel/hierarchy/extension_type_members.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/hierarchy/extension_type_members.dart
@@ -839,12 +839,25 @@
     }
 
     if (definingGetable != null && definingSetable != null) {
-      if (definingGetable.isStatic != definingSetable.isStatic ||
-          definingGetable.isProperty != definingSetable.isProperty) {
+      // TODO(johnniwinther): Should we remove [definingSetable] if we have a
+      // conflict? If we leave it in this conflict will also be reported in
+      // sub-extension types. If  we remove it, any write to the setable will be
+      // unresolved.
+      if (definingGetable.isStatic != definingSetable.isStatic) {
         builder.reportInheritanceConflict(definingGetable, definingSetable);
-        // TODO(johnniwinther): Should we remove [definingSetable]? If we
-        // leave it in this conflict will also be reported in subclasses. If
-        // we remove it, any write to the setable will be unresolved.
+      } else if (definingGetable.isProperty != definingSetable.isProperty) {
+        if (definingGetable.declarationBuilder == builder.declarationBuilder &&
+            definingSetable.declarationBuilder != builder.declarationBuilder) {
+          // The getable precludes the setable.
+          definingSetable = null;
+        } else if (definingSetable.declarationBuilder ==
+                builder.declarationBuilder &&
+            definingGetable.declarationBuilder != builder.declarationBuilder) {
+          // The setable precludes the getable.
+          definingGetable = null;
+        } else {
+          builder.reportInheritanceConflict(definingGetable, definingSetable);
+        }
       }
     }
     return (
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 17bb827..aec0367 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -1190,6 +1190,7 @@
 pre
 prebuild
 prebuilt
+precludes
 precompilation
 precompilations
 precompile
diff --git a/pkg/front_end/testcases/extension_types/issue53720.dart b/pkg/front_end/testcases/extension_types/issue53720.dart
index 5c99cd3..c0dbe50 100644
--- a/pkg/front_end/testcases/extension_types/issue53720.dart
+++ b/pkg/front_end/testcases/extension_types/issue53720.dart
@@ -10,6 +10,6 @@
   void m() {}
 }
 
-void main() {
-  E2(1).m = 10;
+void test() {
+  E2(1).m = 10; /* Error */
 }
\ No newline at end of file
diff --git a/pkg/front_end/testcases/extension_types/issue53720.dart.strong.expect b/pkg/front_end/testcases/extension_types/issue53720.dart.strong.expect
index 62184fd..a02f194 100644
--- a/pkg/front_end/testcases/extension_types/issue53720.dart.strong.expect
+++ b/pkg/front_end/testcases/extension_types/issue53720.dart.strong.expect
@@ -2,12 +2,10 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/extension_types/issue53720.dart:10:8: Error: Can't declare a member that conflicts with an inherited one.
-//   void m() {}
-//        ^
-// pkg/front_end/testcases/extension_types/issue53720.dart:6:7: Context: This is the inherited member.
-//   set m(_) {}
-//       ^
+// pkg/front_end/testcases/extension_types/issue53720.dart:14:9: Error: The setter 'm' isn't defined for the class 'E2'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'm'.
+//   E2(1).m = 10; /* Error */
+//         ^
 //
 import self as self;
 import "dart:core" as core;
@@ -41,6 +39,9 @@
 static extension-type-member method E2|m(lowered final self::E2 /* = core::int */ #this) → void {}
 static extension-type-member method E2|get#m(lowered final self::E2 /* = core::int */ #this) → () → void
   return () → void => self::E2|m(#this);
-static method main() → void {
-  self::E1|set#m(self::E2|constructor#(1), 10);
+static method test() → void {
+  invalid-expression "pkg/front_end/testcases/extension_types/issue53720.dart:14:9: Error: The setter 'm' isn't defined for the class 'E2'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'm'.
+  E2(1).m = 10; /* Error */
+        ^" in self::E2|constructor#(1){<unresolved>}.m = 10;
 }
diff --git a/pkg/front_end/testcases/extension_types/issue53720.dart.strong.transformed.expect b/pkg/front_end/testcases/extension_types/issue53720.dart.strong.transformed.expect
index 62184fd..a02f194 100644
--- a/pkg/front_end/testcases/extension_types/issue53720.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extension_types/issue53720.dart.strong.transformed.expect
@@ -2,12 +2,10 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/extension_types/issue53720.dart:10:8: Error: Can't declare a member that conflicts with an inherited one.
-//   void m() {}
-//        ^
-// pkg/front_end/testcases/extension_types/issue53720.dart:6:7: Context: This is the inherited member.
-//   set m(_) {}
-//       ^
+// pkg/front_end/testcases/extension_types/issue53720.dart:14:9: Error: The setter 'm' isn't defined for the class 'E2'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'm'.
+//   E2(1).m = 10; /* Error */
+//         ^
 //
 import self as self;
 import "dart:core" as core;
@@ -41,6 +39,9 @@
 static extension-type-member method E2|m(lowered final self::E2 /* = core::int */ #this) → void {}
 static extension-type-member method E2|get#m(lowered final self::E2 /* = core::int */ #this) → () → void
   return () → void => self::E2|m(#this);
-static method main() → void {
-  self::E1|set#m(self::E2|constructor#(1), 10);
+static method test() → void {
+  invalid-expression "pkg/front_end/testcases/extension_types/issue53720.dart:14:9: Error: The setter 'm' isn't defined for the class 'E2'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'm'.
+  E2(1).m = 10; /* Error */
+        ^" in self::E2|constructor#(1){<unresolved>}.m = 10;
 }
diff --git a/pkg/front_end/testcases/extension_types/issue53720.dart.textual_outline.expect b/pkg/front_end/testcases/extension_types/issue53720.dart.textual_outline.expect
index 80fe9ad5a..919c885 100644
--- a/pkg/front_end/testcases/extension_types/issue53720.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extension_types/issue53720.dart.textual_outline.expect
@@ -4,4 +4,4 @@
 extension type E2(int i) implements E1 {
   void m() {}
 }
-void main() {}
+void test() {}
diff --git a/pkg/front_end/testcases/extension_types/issue53720.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extension_types/issue53720.dart.textual_outline_modelled.expect
index 80fe9ad5a..919c885 100644
--- a/pkg/front_end/testcases/extension_types/issue53720.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/extension_types/issue53720.dart.textual_outline_modelled.expect
@@ -4,4 +4,4 @@
 extension type E2(int i) implements E1 {
   void m() {}
 }
-void main() {}
+void test() {}
diff --git a/pkg/front_end/testcases/extension_types/issue53720.dart.weak.expect b/pkg/front_end/testcases/extension_types/issue53720.dart.weak.expect
index 62184fd..a02f194 100644
--- a/pkg/front_end/testcases/extension_types/issue53720.dart.weak.expect
+++ b/pkg/front_end/testcases/extension_types/issue53720.dart.weak.expect
@@ -2,12 +2,10 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/extension_types/issue53720.dart:10:8: Error: Can't declare a member that conflicts with an inherited one.
-//   void m() {}
-//        ^
-// pkg/front_end/testcases/extension_types/issue53720.dart:6:7: Context: This is the inherited member.
-//   set m(_) {}
-//       ^
+// pkg/front_end/testcases/extension_types/issue53720.dart:14:9: Error: The setter 'm' isn't defined for the class 'E2'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'm'.
+//   E2(1).m = 10; /* Error */
+//         ^
 //
 import self as self;
 import "dart:core" as core;
@@ -41,6 +39,9 @@
 static extension-type-member method E2|m(lowered final self::E2 /* = core::int */ #this) → void {}
 static extension-type-member method E2|get#m(lowered final self::E2 /* = core::int */ #this) → () → void
   return () → void => self::E2|m(#this);
-static method main() → void {
-  self::E1|set#m(self::E2|constructor#(1), 10);
+static method test() → void {
+  invalid-expression "pkg/front_end/testcases/extension_types/issue53720.dart:14:9: Error: The setter 'm' isn't defined for the class 'E2'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'm'.
+  E2(1).m = 10; /* Error */
+        ^" in self::E2|constructor#(1){<unresolved>}.m = 10;
 }
diff --git a/pkg/front_end/testcases/extension_types/issue53720.dart.weak.modular.expect b/pkg/front_end/testcases/extension_types/issue53720.dart.weak.modular.expect
index 62184fd..a02f194 100644
--- a/pkg/front_end/testcases/extension_types/issue53720.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/extension_types/issue53720.dart.weak.modular.expect
@@ -2,12 +2,10 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/extension_types/issue53720.dart:10:8: Error: Can't declare a member that conflicts with an inherited one.
-//   void m() {}
-//        ^
-// pkg/front_end/testcases/extension_types/issue53720.dart:6:7: Context: This is the inherited member.
-//   set m(_) {}
-//       ^
+// pkg/front_end/testcases/extension_types/issue53720.dart:14:9: Error: The setter 'm' isn't defined for the class 'E2'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'm'.
+//   E2(1).m = 10; /* Error */
+//         ^
 //
 import self as self;
 import "dart:core" as core;
@@ -41,6 +39,9 @@
 static extension-type-member method E2|m(lowered final self::E2 /* = core::int */ #this) → void {}
 static extension-type-member method E2|get#m(lowered final self::E2 /* = core::int */ #this) → () → void
   return () → void => self::E2|m(#this);
-static method main() → void {
-  self::E1|set#m(self::E2|constructor#(1), 10);
+static method test() → void {
+  invalid-expression "pkg/front_end/testcases/extension_types/issue53720.dart:14:9: Error: The setter 'm' isn't defined for the class 'E2'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'm'.
+  E2(1).m = 10; /* Error */
+        ^" in self::E2|constructor#(1){<unresolved>}.m = 10;
 }
diff --git a/pkg/front_end/testcases/extension_types/issue53720.dart.weak.outline.expect b/pkg/front_end/testcases/extension_types/issue53720.dart.weak.outline.expect
index 5d3c1a5..ee47ec0 100644
--- a/pkg/front_end/testcases/extension_types/issue53720.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/extension_types/issue53720.dart.weak.outline.expect
@@ -1,14 +1,4 @@
 library;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/extension_types/issue53720.dart:10:8: Error: Can't declare a member that conflicts with an inherited one.
-//   void m() {}
-//        ^
-// pkg/front_end/testcases/extension_types/issue53720.dart:6:7: Context: This is the inherited member.
-//   set m(_) {}
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -39,5 +29,5 @@
   ;
 static extension-type-member method E2|get#m(lowered final self::E2 /* = core::int */ #this) → () → void
   return () → void => self::E2|m(#this);
-static method main() → void
+static method test() → void
   ;
diff --git a/pkg/front_end/testcases/extension_types/issue53720.dart.weak.transformed.expect b/pkg/front_end/testcases/extension_types/issue53720.dart.weak.transformed.expect
index 62184fd..a02f194 100644
--- a/pkg/front_end/testcases/extension_types/issue53720.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extension_types/issue53720.dart.weak.transformed.expect
@@ -2,12 +2,10 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/extension_types/issue53720.dart:10:8: Error: Can't declare a member that conflicts with an inherited one.
-//   void m() {}
-//        ^
-// pkg/front_end/testcases/extension_types/issue53720.dart:6:7: Context: This is the inherited member.
-//   set m(_) {}
-//       ^
+// pkg/front_end/testcases/extension_types/issue53720.dart:14:9: Error: The setter 'm' isn't defined for the class 'E2'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'm'.
+//   E2(1).m = 10; /* Error */
+//         ^
 //
 import self as self;
 import "dart:core" as core;
@@ -41,6 +39,9 @@
 static extension-type-member method E2|m(lowered final self::E2 /* = core::int */ #this) → void {}
 static extension-type-member method E2|get#m(lowered final self::E2 /* = core::int */ #this) → () → void
   return () → void => self::E2|m(#this);
-static method main() → void {
-  self::E1|set#m(self::E2|constructor#(1), 10);
+static method test() → void {
+  invalid-expression "pkg/front_end/testcases/extension_types/issue53720.dart:14:9: Error: The setter 'm' isn't defined for the class 'E2'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'm'.
+  E2(1).m = 10; /* Error */
+        ^" in self::E2|constructor#(1){<unresolved>}.m = 10;
 }
diff --git a/pkg/front_end/testcases/extension_types/issue53720_2.dart b/pkg/front_end/testcases/extension_types/issue53720_2.dart
new file mode 100644
index 0000000..a84c83f
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/issue53720_2.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by b
+// BSD-style license that can be found in the LICENSE file.
+
+extension type E1(int i) {
+  set m1(_) {}
+  void m2() {}
+  get m3 => 1;
+  set m4(_) {}
+}
+
+extension type E2(int i) implements E1 {
+  void m1() {} // OK, and `E2` does not have a setter named `m1=`.
+  set m2(_) {} // OK, and `E2` does not have a method named `m2`.
+  set m3(_) {} // OK, and `E2` has the full getter/setter pair.
+  get m4 => 1; // OK, and `E2` has the full getter/setter pair.
+}
+
+void test() {
+  var e2 = E2(1);
+  e2.m1(); // OK.
+  e2.m1 = 10; // Compile-time error.
+  e2.m2 = 10; // OK.
+  e2.m2(); // Compile-time error.
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/extension_types/issue53720_2.dart.strong.expect b/pkg/front_end/testcases/extension_types/issue53720_2.dart.strong.expect
new file mode 100644
index 0000000..2a6f44a
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/issue53720_2.dart.strong.expect
@@ -0,0 +1,76 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/issue53720_2.dart:22:6: Error: The setter 'm1' isn't defined for the class 'E2'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'm1'.
+//   e2.m1 = 10; // Compile-time error.
+//      ^^
+//
+// pkg/front_end/testcases/extension_types/issue53720_2.dart:24:6: Error: The method 'm2' isn't defined for the class 'E2'.
+// Try correcting the name to the name of an existing method, or defining a method named 'm2'.
+//   e2.m2(); // Compile-time error.
+//      ^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension type E1(core::int i) {
+  abstract extension-type-member representation-field get i() → core::int;
+  method m2 = self::E1|m2;
+  method tearoff m2 = self::E1|get#m2;
+  get m3 = self::E1|get#m3;
+  set m1 = self::E1|set#m1;
+  set m4 = self::E1|set#m4;
+  constructor • = self::E1|constructor#;
+  constructor tearoff • = self::E1|constructor#_#new#tearOff;
+}
+extension type E2(core::int i) implements self::E1 /* = core::int */ {
+  abstract extension-type-member representation-field get i() → core::int;
+  method m1 = self::E2|m1;
+  method tearoff m1 = self::E2|get#m1;
+  get m4 = self::E2|get#m4;
+  set m2 = self::E2|set#m2;
+  set m3 = self::E2|set#m3;
+  constructor • = self::E2|constructor#;
+  constructor tearoff • = self::E2|constructor#_#new#tearOff;
+}
+static extension-type-member method E1|constructor#(core::int i) → self::E1 /* = core::int */ {
+  lowered final self::E1 /* = core::int */ #this = i;
+  return #this;
+}
+static extension-type-member method E1|constructor#_#new#tearOff(core::int i) → self::E1 /* = core::int */
+  return self::E1|constructor#(i);
+static extension-type-member method E1|set#m1(lowered final self::E1 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E1|m2(lowered final self::E1 /* = core::int */ #this) → void {}
+static extension-type-member method E1|get#m2(lowered final self::E1 /* = core::int */ #this) → () → void
+  return () → void => self::E1|m2(#this);
+static extension-type-member method E1|get#m3(lowered final self::E1 /* = core::int */ #this) → dynamic
+  return 1;
+static extension-type-member method E1|set#m4(lowered final self::E1 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E2|constructor#(core::int i) → self::E2 /* = core::int */ {
+  lowered final self::E2 /* = core::int */ #this = i;
+  return #this;
+}
+static extension-type-member method E2|constructor#_#new#tearOff(core::int i) → self::E2 /* = core::int */
+  return self::E2|constructor#(i);
+static extension-type-member method E2|m1(lowered final self::E2 /* = core::int */ #this) → void {}
+static extension-type-member method E2|get#m1(lowered final self::E2 /* = core::int */ #this) → () → void
+  return () → void => self::E2|m1(#this);
+static extension-type-member method E2|set#m2(lowered final self::E2 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E2|set#m3(lowered final self::E2 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E2|get#m4(lowered final self::E2 /* = core::int */ #this) → dynamic
+  return 1;
+static method test() → void {
+  self::E2 /* = core::int */ e2 = self::E2|constructor#(1);
+  self::E2|m1(e2);
+  invalid-expression "pkg/front_end/testcases/extension_types/issue53720_2.dart:22:6: Error: The setter 'm1' isn't defined for the class 'E2'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'm1'.
+  e2.m1 = 10; // Compile-time error.
+     ^^" in e2{<unresolved>}.m1 = 10;
+  self::E2|set#m2(e2, 10);
+  invalid-expression "pkg/front_end/testcases/extension_types/issue53720_2.dart:24:6: Error: The method 'm2' isn't defined for the class 'E2'.
+Try correcting the name to the name of an existing method, or defining a method named 'm2'.
+  e2.m2(); // Compile-time error.
+     ^^" in e2{<unresolved>}.m2();
+}
diff --git a/pkg/front_end/testcases/extension_types/issue53720_2.dart.strong.transformed.expect b/pkg/front_end/testcases/extension_types/issue53720_2.dart.strong.transformed.expect
new file mode 100644
index 0000000..2a6f44a
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/issue53720_2.dart.strong.transformed.expect
@@ -0,0 +1,76 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/issue53720_2.dart:22:6: Error: The setter 'm1' isn't defined for the class 'E2'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'm1'.
+//   e2.m1 = 10; // Compile-time error.
+//      ^^
+//
+// pkg/front_end/testcases/extension_types/issue53720_2.dart:24:6: Error: The method 'm2' isn't defined for the class 'E2'.
+// Try correcting the name to the name of an existing method, or defining a method named 'm2'.
+//   e2.m2(); // Compile-time error.
+//      ^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension type E1(core::int i) {
+  abstract extension-type-member representation-field get i() → core::int;
+  method m2 = self::E1|m2;
+  method tearoff m2 = self::E1|get#m2;
+  get m3 = self::E1|get#m3;
+  set m1 = self::E1|set#m1;
+  set m4 = self::E1|set#m4;
+  constructor • = self::E1|constructor#;
+  constructor tearoff • = self::E1|constructor#_#new#tearOff;
+}
+extension type E2(core::int i) implements self::E1 /* = core::int */ {
+  abstract extension-type-member representation-field get i() → core::int;
+  method m1 = self::E2|m1;
+  method tearoff m1 = self::E2|get#m1;
+  get m4 = self::E2|get#m4;
+  set m2 = self::E2|set#m2;
+  set m3 = self::E2|set#m3;
+  constructor • = self::E2|constructor#;
+  constructor tearoff • = self::E2|constructor#_#new#tearOff;
+}
+static extension-type-member method E1|constructor#(core::int i) → self::E1 /* = core::int */ {
+  lowered final self::E1 /* = core::int */ #this = i;
+  return #this;
+}
+static extension-type-member method E1|constructor#_#new#tearOff(core::int i) → self::E1 /* = core::int */
+  return self::E1|constructor#(i);
+static extension-type-member method E1|set#m1(lowered final self::E1 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E1|m2(lowered final self::E1 /* = core::int */ #this) → void {}
+static extension-type-member method E1|get#m2(lowered final self::E1 /* = core::int */ #this) → () → void
+  return () → void => self::E1|m2(#this);
+static extension-type-member method E1|get#m3(lowered final self::E1 /* = core::int */ #this) → dynamic
+  return 1;
+static extension-type-member method E1|set#m4(lowered final self::E1 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E2|constructor#(core::int i) → self::E2 /* = core::int */ {
+  lowered final self::E2 /* = core::int */ #this = i;
+  return #this;
+}
+static extension-type-member method E2|constructor#_#new#tearOff(core::int i) → self::E2 /* = core::int */
+  return self::E2|constructor#(i);
+static extension-type-member method E2|m1(lowered final self::E2 /* = core::int */ #this) → void {}
+static extension-type-member method E2|get#m1(lowered final self::E2 /* = core::int */ #this) → () → void
+  return () → void => self::E2|m1(#this);
+static extension-type-member method E2|set#m2(lowered final self::E2 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E2|set#m3(lowered final self::E2 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E2|get#m4(lowered final self::E2 /* = core::int */ #this) → dynamic
+  return 1;
+static method test() → void {
+  self::E2 /* = core::int */ e2 = self::E2|constructor#(1);
+  self::E2|m1(e2);
+  invalid-expression "pkg/front_end/testcases/extension_types/issue53720_2.dart:22:6: Error: The setter 'm1' isn't defined for the class 'E2'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'm1'.
+  e2.m1 = 10; // Compile-time error.
+     ^^" in e2{<unresolved>}.m1 = 10;
+  self::E2|set#m2(e2, 10);
+  invalid-expression "pkg/front_end/testcases/extension_types/issue53720_2.dart:24:6: Error: The method 'm2' isn't defined for the class 'E2'.
+Try correcting the name to the name of an existing method, or defining a method named 'm2'.
+  e2.m2(); // Compile-time error.
+     ^^" in e2{<unresolved>}.m2();
+}
diff --git a/pkg/front_end/testcases/extension_types/issue53720_2.dart.textual_outline.expect b/pkg/front_end/testcases/extension_types/issue53720_2.dart.textual_outline.expect
new file mode 100644
index 0000000..2c92e35
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/issue53720_2.dart.textual_outline.expect
@@ -0,0 +1,13 @@
+extension type E1(int i) {
+  set m1(_) {}
+  void m2() {}
+  get m3 => 1;
+  set m4(_) {}
+}
+extension type E2(int i) implements E1 {
+  void m1() {}
+  set m2(_) {}
+  set m3(_) {}
+  get m4 => 1;
+}
+void test() {}
diff --git a/pkg/front_end/testcases/extension_types/issue53720_2.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extension_types/issue53720_2.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..52b6581
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/issue53720_2.dart.textual_outline_modelled.expect
@@ -0,0 +1,13 @@
+extension type E1(int i) {
+  get m3 => 1;
+  set m1(_) {}
+  set m4(_) {}
+  void m2() {}
+}
+extension type E2(int i) implements E1 {
+  get m4 => 1;
+  set m2(_) {}
+  set m3(_) {}
+  void m1() {}
+}
+void test() {}
diff --git a/pkg/front_end/testcases/extension_types/issue53720_2.dart.weak.expect b/pkg/front_end/testcases/extension_types/issue53720_2.dart.weak.expect
new file mode 100644
index 0000000..2a6f44a
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/issue53720_2.dart.weak.expect
@@ -0,0 +1,76 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/issue53720_2.dart:22:6: Error: The setter 'm1' isn't defined for the class 'E2'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'm1'.
+//   e2.m1 = 10; // Compile-time error.
+//      ^^
+//
+// pkg/front_end/testcases/extension_types/issue53720_2.dart:24:6: Error: The method 'm2' isn't defined for the class 'E2'.
+// Try correcting the name to the name of an existing method, or defining a method named 'm2'.
+//   e2.m2(); // Compile-time error.
+//      ^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension type E1(core::int i) {
+  abstract extension-type-member representation-field get i() → core::int;
+  method m2 = self::E1|m2;
+  method tearoff m2 = self::E1|get#m2;
+  get m3 = self::E1|get#m3;
+  set m1 = self::E1|set#m1;
+  set m4 = self::E1|set#m4;
+  constructor • = self::E1|constructor#;
+  constructor tearoff • = self::E1|constructor#_#new#tearOff;
+}
+extension type E2(core::int i) implements self::E1 /* = core::int */ {
+  abstract extension-type-member representation-field get i() → core::int;
+  method m1 = self::E2|m1;
+  method tearoff m1 = self::E2|get#m1;
+  get m4 = self::E2|get#m4;
+  set m2 = self::E2|set#m2;
+  set m3 = self::E2|set#m3;
+  constructor • = self::E2|constructor#;
+  constructor tearoff • = self::E2|constructor#_#new#tearOff;
+}
+static extension-type-member method E1|constructor#(core::int i) → self::E1 /* = core::int */ {
+  lowered final self::E1 /* = core::int */ #this = i;
+  return #this;
+}
+static extension-type-member method E1|constructor#_#new#tearOff(core::int i) → self::E1 /* = core::int */
+  return self::E1|constructor#(i);
+static extension-type-member method E1|set#m1(lowered final self::E1 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E1|m2(lowered final self::E1 /* = core::int */ #this) → void {}
+static extension-type-member method E1|get#m2(lowered final self::E1 /* = core::int */ #this) → () → void
+  return () → void => self::E1|m2(#this);
+static extension-type-member method E1|get#m3(lowered final self::E1 /* = core::int */ #this) → dynamic
+  return 1;
+static extension-type-member method E1|set#m4(lowered final self::E1 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E2|constructor#(core::int i) → self::E2 /* = core::int */ {
+  lowered final self::E2 /* = core::int */ #this = i;
+  return #this;
+}
+static extension-type-member method E2|constructor#_#new#tearOff(core::int i) → self::E2 /* = core::int */
+  return self::E2|constructor#(i);
+static extension-type-member method E2|m1(lowered final self::E2 /* = core::int */ #this) → void {}
+static extension-type-member method E2|get#m1(lowered final self::E2 /* = core::int */ #this) → () → void
+  return () → void => self::E2|m1(#this);
+static extension-type-member method E2|set#m2(lowered final self::E2 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E2|set#m3(lowered final self::E2 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E2|get#m4(lowered final self::E2 /* = core::int */ #this) → dynamic
+  return 1;
+static method test() → void {
+  self::E2 /* = core::int */ e2 = self::E2|constructor#(1);
+  self::E2|m1(e2);
+  invalid-expression "pkg/front_end/testcases/extension_types/issue53720_2.dart:22:6: Error: The setter 'm1' isn't defined for the class 'E2'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'm1'.
+  e2.m1 = 10; // Compile-time error.
+     ^^" in e2{<unresolved>}.m1 = 10;
+  self::E2|set#m2(e2, 10);
+  invalid-expression "pkg/front_end/testcases/extension_types/issue53720_2.dart:24:6: Error: The method 'm2' isn't defined for the class 'E2'.
+Try correcting the name to the name of an existing method, or defining a method named 'm2'.
+  e2.m2(); // Compile-time error.
+     ^^" in e2{<unresolved>}.m2();
+}
diff --git a/pkg/front_end/testcases/extension_types/issue53720_2.dart.weak.modular.expect b/pkg/front_end/testcases/extension_types/issue53720_2.dart.weak.modular.expect
new file mode 100644
index 0000000..2a6f44a
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/issue53720_2.dart.weak.modular.expect
@@ -0,0 +1,76 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/issue53720_2.dart:22:6: Error: The setter 'm1' isn't defined for the class 'E2'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'm1'.
+//   e2.m1 = 10; // Compile-time error.
+//      ^^
+//
+// pkg/front_end/testcases/extension_types/issue53720_2.dart:24:6: Error: The method 'm2' isn't defined for the class 'E2'.
+// Try correcting the name to the name of an existing method, or defining a method named 'm2'.
+//   e2.m2(); // Compile-time error.
+//      ^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension type E1(core::int i) {
+  abstract extension-type-member representation-field get i() → core::int;
+  method m2 = self::E1|m2;
+  method tearoff m2 = self::E1|get#m2;
+  get m3 = self::E1|get#m3;
+  set m1 = self::E1|set#m1;
+  set m4 = self::E1|set#m4;
+  constructor • = self::E1|constructor#;
+  constructor tearoff • = self::E1|constructor#_#new#tearOff;
+}
+extension type E2(core::int i) implements self::E1 /* = core::int */ {
+  abstract extension-type-member representation-field get i() → core::int;
+  method m1 = self::E2|m1;
+  method tearoff m1 = self::E2|get#m1;
+  get m4 = self::E2|get#m4;
+  set m2 = self::E2|set#m2;
+  set m3 = self::E2|set#m3;
+  constructor • = self::E2|constructor#;
+  constructor tearoff • = self::E2|constructor#_#new#tearOff;
+}
+static extension-type-member method E1|constructor#(core::int i) → self::E1 /* = core::int */ {
+  lowered final self::E1 /* = core::int */ #this = i;
+  return #this;
+}
+static extension-type-member method E1|constructor#_#new#tearOff(core::int i) → self::E1 /* = core::int */
+  return self::E1|constructor#(i);
+static extension-type-member method E1|set#m1(lowered final self::E1 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E1|m2(lowered final self::E1 /* = core::int */ #this) → void {}
+static extension-type-member method E1|get#m2(lowered final self::E1 /* = core::int */ #this) → () → void
+  return () → void => self::E1|m2(#this);
+static extension-type-member method E1|get#m3(lowered final self::E1 /* = core::int */ #this) → dynamic
+  return 1;
+static extension-type-member method E1|set#m4(lowered final self::E1 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E2|constructor#(core::int i) → self::E2 /* = core::int */ {
+  lowered final self::E2 /* = core::int */ #this = i;
+  return #this;
+}
+static extension-type-member method E2|constructor#_#new#tearOff(core::int i) → self::E2 /* = core::int */
+  return self::E2|constructor#(i);
+static extension-type-member method E2|m1(lowered final self::E2 /* = core::int */ #this) → void {}
+static extension-type-member method E2|get#m1(lowered final self::E2 /* = core::int */ #this) → () → void
+  return () → void => self::E2|m1(#this);
+static extension-type-member method E2|set#m2(lowered final self::E2 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E2|set#m3(lowered final self::E2 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E2|get#m4(lowered final self::E2 /* = core::int */ #this) → dynamic
+  return 1;
+static method test() → void {
+  self::E2 /* = core::int */ e2 = self::E2|constructor#(1);
+  self::E2|m1(e2);
+  invalid-expression "pkg/front_end/testcases/extension_types/issue53720_2.dart:22:6: Error: The setter 'm1' isn't defined for the class 'E2'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'm1'.
+  e2.m1 = 10; // Compile-time error.
+     ^^" in e2{<unresolved>}.m1 = 10;
+  self::E2|set#m2(e2, 10);
+  invalid-expression "pkg/front_end/testcases/extension_types/issue53720_2.dart:24:6: Error: The method 'm2' isn't defined for the class 'E2'.
+Try correcting the name to the name of an existing method, or defining a method named 'm2'.
+  e2.m2(); // Compile-time error.
+     ^^" in e2{<unresolved>}.m2();
+}
diff --git a/pkg/front_end/testcases/extension_types/issue53720_2.dart.weak.outline.expect b/pkg/front_end/testcases/extension_types/issue53720_2.dart.weak.outline.expect
new file mode 100644
index 0000000..17b21b1
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/issue53720_2.dart.weak.outline.expect
@@ -0,0 +1,54 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+extension type E1(core::int i) {
+  abstract extension-type-member representation-field get i() → core::int;
+  method m2 = self::E1|m2;
+  method tearoff m2 = self::E1|get#m2;
+  get m3 = self::E1|get#m3;
+  set m1 = self::E1|set#m1;
+  set m4 = self::E1|set#m4;
+  constructor • = self::E1|constructor#;
+  constructor tearoff • = self::E1|constructor#_#new#tearOff;
+}
+extension type E2(core::int i) implements self::E1 /* = core::int */ {
+  abstract extension-type-member representation-field get i() → core::int;
+  method m1 = self::E2|m1;
+  method tearoff m1 = self::E2|get#m1;
+  get m4 = self::E2|get#m4;
+  set m2 = self::E2|set#m2;
+  set m3 = self::E2|set#m3;
+  constructor • = self::E2|constructor#;
+  constructor tearoff • = self::E2|constructor#_#new#tearOff;
+}
+static extension-type-member method E1|constructor#(core::int i) → self::E1 /* = core::int */
+  ;
+static extension-type-member method E1|constructor#_#new#tearOff(core::int i) → self::E1 /* = core::int */
+  return self::E1|constructor#(i);
+static extension-type-member method E1|set#m1(lowered final self::E1 /* = core::int */ #this, dynamic _) → void
+  ;
+static extension-type-member method E1|m2(lowered final self::E1 /* = core::int */ #this) → void
+  ;
+static extension-type-member method E1|get#m2(lowered final self::E1 /* = core::int */ #this) → () → void
+  return () → void => self::E1|m2(#this);
+static extension-type-member method E1|get#m3(lowered final self::E1 /* = core::int */ #this) → dynamic
+  ;
+static extension-type-member method E1|set#m4(lowered final self::E1 /* = core::int */ #this, dynamic _) → void
+  ;
+static extension-type-member method E2|constructor#(core::int i) → self::E2 /* = core::int */
+  ;
+static extension-type-member method E2|constructor#_#new#tearOff(core::int i) → self::E2 /* = core::int */
+  return self::E2|constructor#(i);
+static extension-type-member method E2|m1(lowered final self::E2 /* = core::int */ #this) → void
+  ;
+static extension-type-member method E2|get#m1(lowered final self::E2 /* = core::int */ #this) → () → void
+  return () → void => self::E2|m1(#this);
+static extension-type-member method E2|set#m2(lowered final self::E2 /* = core::int */ #this, dynamic _) → void
+  ;
+static extension-type-member method E2|set#m3(lowered final self::E2 /* = core::int */ #this, dynamic _) → void
+  ;
+static extension-type-member method E2|get#m4(lowered final self::E2 /* = core::int */ #this) → dynamic
+  ;
+static method test() → void
+  ;
diff --git a/pkg/front_end/testcases/extension_types/issue53720_2.dart.weak.transformed.expect b/pkg/front_end/testcases/extension_types/issue53720_2.dart.weak.transformed.expect
new file mode 100644
index 0000000..2a6f44a
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/issue53720_2.dart.weak.transformed.expect
@@ -0,0 +1,76 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/issue53720_2.dart:22:6: Error: The setter 'm1' isn't defined for the class 'E2'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'm1'.
+//   e2.m1 = 10; // Compile-time error.
+//      ^^
+//
+// pkg/front_end/testcases/extension_types/issue53720_2.dart:24:6: Error: The method 'm2' isn't defined for the class 'E2'.
+// Try correcting the name to the name of an existing method, or defining a method named 'm2'.
+//   e2.m2(); // Compile-time error.
+//      ^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension type E1(core::int i) {
+  abstract extension-type-member representation-field get i() → core::int;
+  method m2 = self::E1|m2;
+  method tearoff m2 = self::E1|get#m2;
+  get m3 = self::E1|get#m3;
+  set m1 = self::E1|set#m1;
+  set m4 = self::E1|set#m4;
+  constructor • = self::E1|constructor#;
+  constructor tearoff • = self::E1|constructor#_#new#tearOff;
+}
+extension type E2(core::int i) implements self::E1 /* = core::int */ {
+  abstract extension-type-member representation-field get i() → core::int;
+  method m1 = self::E2|m1;
+  method tearoff m1 = self::E2|get#m1;
+  get m4 = self::E2|get#m4;
+  set m2 = self::E2|set#m2;
+  set m3 = self::E2|set#m3;
+  constructor • = self::E2|constructor#;
+  constructor tearoff • = self::E2|constructor#_#new#tearOff;
+}
+static extension-type-member method E1|constructor#(core::int i) → self::E1 /* = core::int */ {
+  lowered final self::E1 /* = core::int */ #this = i;
+  return #this;
+}
+static extension-type-member method E1|constructor#_#new#tearOff(core::int i) → self::E1 /* = core::int */
+  return self::E1|constructor#(i);
+static extension-type-member method E1|set#m1(lowered final self::E1 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E1|m2(lowered final self::E1 /* = core::int */ #this) → void {}
+static extension-type-member method E1|get#m2(lowered final self::E1 /* = core::int */ #this) → () → void
+  return () → void => self::E1|m2(#this);
+static extension-type-member method E1|get#m3(lowered final self::E1 /* = core::int */ #this) → dynamic
+  return 1;
+static extension-type-member method E1|set#m4(lowered final self::E1 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E2|constructor#(core::int i) → self::E2 /* = core::int */ {
+  lowered final self::E2 /* = core::int */ #this = i;
+  return #this;
+}
+static extension-type-member method E2|constructor#_#new#tearOff(core::int i) → self::E2 /* = core::int */
+  return self::E2|constructor#(i);
+static extension-type-member method E2|m1(lowered final self::E2 /* = core::int */ #this) → void {}
+static extension-type-member method E2|get#m1(lowered final self::E2 /* = core::int */ #this) → () → void
+  return () → void => self::E2|m1(#this);
+static extension-type-member method E2|set#m2(lowered final self::E2 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E2|set#m3(lowered final self::E2 /* = core::int */ #this, dynamic _) → void {}
+static extension-type-member method E2|get#m4(lowered final self::E2 /* = core::int */ #this) → dynamic
+  return 1;
+static method test() → void {
+  self::E2 /* = core::int */ e2 = self::E2|constructor#(1);
+  self::E2|m1(e2);
+  invalid-expression "pkg/front_end/testcases/extension_types/issue53720_2.dart:22:6: Error: The setter 'm1' isn't defined for the class 'E2'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'm1'.
+  e2.m1 = 10; // Compile-time error.
+     ^^" in e2{<unresolved>}.m1 = 10;
+  self::E2|set#m2(e2, 10);
+  invalid-expression "pkg/front_end/testcases/extension_types/issue53720_2.dart:24:6: Error: The method 'm2' isn't defined for the class 'E2'.
+Try correcting the name to the name of an existing method, or defining a method named 'm2'.
+  e2.m2(); // Compile-time error.
+     ^^" in e2{<unresolved>}.m2();
+}