[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();
+}