[cfe] Add ExtensionTypeHierarchyNode(Builder)
This adds checks for conflicting supertypes and prepares for computation
of extension type members.
Change-Id: If997fe84bac929274a6014b315ecea4f3856eedd
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/315441
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
diff --git a/pkg/front_end/lib/src/fasta/builder/inline_class_builder.dart b/pkg/front_end/lib/src/fasta/builder/inline_class_builder.dart
index 92e3d53..0f95412 100644
--- a/pkg/front_end/lib/src/fasta/builder/inline_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/inline_class_builder.dart
@@ -25,6 +25,10 @@
/// Return the [InlineClass] built by this builder.
InlineClass get inlineClass;
+ /// Returns a list of the classes and extension types implemented by this
+ /// extension type.
+ List<TypeBuilder>? get interfaceBuilders;
+
/// Looks up inline class member by [name] taking privacy into account.
///
/// If [setter] is `true` the sought member is a setter or assignable field.
@@ -40,6 +44,9 @@
/// Calls [f] for each member declared in this extension.
void forEach(void f(String name, Builder builder));
+
+ @override
+ Uri get fileUri;
}
abstract class InlineClassBuilderImpl extends DeclarationBuilderImpl
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_loader.dart b/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
index bc994b4..13c75df 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
@@ -6,9 +6,11 @@
import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
-import 'package:kernel/ast.dart' show Class, Component, DartType, Library;
+import 'package:kernel/ast.dart'
+ show Class, Component, DartType, InlineClass, Library;
import '../builder/class_builder.dart';
+import '../builder/inline_class_builder.dart';
import '../builder/library_builder.dart';
import '../builder/type_builder.dart';
@@ -331,6 +333,19 @@
return library!.lookupLocalMember(cls.name, required: true) as ClassBuilder;
}
+ @override
+ InlineClassBuilder computeExtensionTypeBuilderFromTargetExtensionType(
+ InlineClass extensionType) {
+ Library kernelLibrary = extensionType.enclosingLibrary;
+ LibraryBuilder? library = lookupLibraryBuilder(kernelLibrary.importUri);
+ if (library == null) {
+ library =
+ currentSourceLoader?.lookupLibraryBuilder(kernelLibrary.importUri);
+ }
+ return library!.lookupLocalMember(extensionType.name, required: true)
+ as InlineClassBuilder;
+ }
+
late TypeBuilderComputer _typeBuilderComputer = new TypeBuilderComputer(this);
@override
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 8c3421c..4f26a28 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -1497,7 +1497,7 @@
// Get all classes touched by fasta class hierarchy.
if (builderHierarchy != null) {
- for (Class c in builderHierarchy.nodes.keys) {
+ for (Class c in builderHierarchy.classNodes.keys) {
if (classes.add(c)) worklist.add(c);
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/hierarchy/hierarchy_builder.dart b/pkg/front_end/lib/src/fasta/kernel/hierarchy/hierarchy_builder.dart
index 19f1592..55e6c66 100644
--- a/pkg/front_end/lib/src/fasta/kernel/hierarchy/hierarchy_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/hierarchy/hierarchy_builder.dart
@@ -12,15 +12,19 @@
import 'package:kernel/type_algebra.dart' show Substitution, uniteNullabilities;
import '../../builder/class_builder.dart';
-import '../../builder/type_builder.dart';
+import '../../builder/inline_class_builder.dart';
import '../../loader.dart' show Loader;
+import '../../source/source_class_builder.dart';
+import '../../source/source_inline_class_builder.dart';
import '../../source/source_loader.dart' show SourceLoader;
import 'hierarchy_node.dart';
class ClassHierarchyBuilder
with ClassHierarchyInlineClassMixin
implements ClassHierarchyBase {
- final Map<Class, ClassHierarchyNode> nodes = <Class, ClassHierarchyNode>{};
+ final Map<Class, ClassHierarchyNode> classNodes = {};
+
+ final Map<InlineClass, ExtensionTypeHierarchyNode> extensionTypeNodes = {};
final ClassBuilder objectClassBuilder;
@@ -45,22 +49,32 @@
}
void clear() {
- nodes.clear();
+ classNodes.clear();
+ extensionTypeNodes.clear();
}
ClassHierarchyNode getNodeFromClassBuilder(ClassBuilder classBuilder) {
- return nodes[classBuilder.cls] ??=
+ return classNodes[classBuilder.cls] ??=
new ClassHierarchyNodeBuilder(this, classBuilder).build();
}
- ClassHierarchyNode? getNodeFromTypeBuilder(TypeBuilder type) {
- ClassBuilder? cls = getClass(type);
- return cls == null ? null : getNodeFromClassBuilder(cls);
+ ClassHierarchyNode getNodeFromClass(Class cls) {
+ return classNodes[cls] ??
+ getNodeFromClassBuilder(loader.computeClassBuilderFromTargetClass(cls));
}
- ClassHierarchyNode getNodeFromClass(Class cls) {
- return nodes[cls] ??
- getNodeFromClassBuilder(loader.computeClassBuilderFromTargetClass(cls));
+ ExtensionTypeHierarchyNode getNodeFromExtensionTypeBuilder(
+ InlineClassBuilder extensionTypeBuilder) {
+ return extensionTypeNodes[extensionTypeBuilder.inlineClass] ??=
+ new ExtensionTypeHierarchyNodeBuilder(this, extensionTypeBuilder)
+ .build();
+ }
+
+ ExtensionTypeHierarchyNode getNodeFromExtensionType(
+ InlineClass extensionType) {
+ return extensionTypeNodes[extensionType] ??
+ getNodeFromExtensionTypeBuilder(loader
+ .computeExtensionTypeBuilderFromTargetExtensionType(extensionType));
}
Supertype? asSupertypeOf(InterfaceType subtype, Class supertype) {
@@ -183,19 +197,26 @@
uniteNullabilities(type1.nullability, type2.nullability));
}
- static ClassHierarchyBuilder build(ClassBuilder objectClass,
- List<ClassBuilder> classes, SourceLoader loader, CoreTypes coreTypes) {
+ static ClassHierarchyBuilder build(
+ ClassBuilder objectClass,
+ List<SourceClassBuilder> classes,
+ List<SourceInlineClassBuilder> extensionTypes,
+ SourceLoader loader,
+ CoreTypes coreTypes) {
ClassHierarchyBuilder hierarchy =
new ClassHierarchyBuilder(objectClass, loader, coreTypes);
for (int i = 0; i < classes.length; i++) {
- ClassBuilder classBuilder = classes[i];
- if (!classBuilder.isPatch) {
- hierarchy.nodes[classBuilder.cls] =
- new ClassHierarchyNodeBuilder(hierarchy, classBuilder).build();
- } else {
- // TODO(ahe): Merge the injected members of patch into the hierarchy
- // node of `cls.origin`.
- }
+ SourceClassBuilder classBuilder = classes[i];
+ assert(!classBuilder.isPatch);
+ hierarchy.classNodes[classBuilder.cls] =
+ new ClassHierarchyNodeBuilder(hierarchy, classBuilder).build();
+ }
+ for (int i = 0; i < extensionTypes.length; i++) {
+ SourceInlineClassBuilder extensionTypeBuilder = extensionTypes[i];
+ assert(!extensionTypeBuilder.isPatch);
+ hierarchy.extensionTypeNodes[extensionTypeBuilder.inlineClass] =
+ new ExtensionTypeHierarchyNodeBuilder(hierarchy, extensionTypeBuilder)
+ .build();
}
return hierarchy;
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/hierarchy/hierarchy_node.dart b/pkg/front_end/lib/src/fasta/kernel/hierarchy/hierarchy_node.dart
index 4d5141a..18695d4 100644
--- a/pkg/front_end/lib/src/fasta/kernel/hierarchy/hierarchy_node.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/hierarchy/hierarchy_node.dart
@@ -13,6 +13,7 @@
import '../../../testing/id_testing_utils.dart' show typeToText;
import '../../builder/builder.dart';
import '../../builder/class_builder.dart';
+import '../../builder/inline_class_builder.dart';
import '../../builder/library_builder.dart';
import '../../builder/named_type_builder.dart';
import '../../builder/type_alias_builder.dart';
@@ -23,145 +24,50 @@
import 'hierarchy_builder.dart';
import 'mixin_inferrer.dart';
-class ClassHierarchyNodeBuilder {
- final ClassHierarchyBuilder hierarchy;
+abstract class HierarchyNodeBuilder {
+ final ClassHierarchyBuilder _hierarchy;
- final ClassBuilder classBuilder;
+ HierarchyNodeBuilder(this._hierarchy);
- bool hasNoSuchMethod = false;
+ LibraryBuilder get _libraryBuilder;
- ClassHierarchyNodeBuilder(this.hierarchy, this.classBuilder);
+ String get _name;
- ClassBuilder get objectClass => hierarchy.objectClassBuilder;
+ int get _fileOffset;
- ClassHierarchyNode build() {
- assert(!classBuilder.isPatch);
- ClassHierarchyNode? supernode;
- if (objectClass != classBuilder.origin) {
- supernode =
- hierarchy.getNodeFromTypeBuilder(classBuilder.supertypeBuilder!);
- if (supernode == null) {
- supernode = hierarchy.getNodeFromClassBuilder(objectClass);
+ Uri get _fileUri;
+
+ Supertype _resolveSupertypeConflict(Supertype type, Supertype superclass) {
+ if (_libraryBuilder.isNonNullableByDefault) {
+ Supertype? merge = nnbdTopMergeSupertype(
+ _hierarchy.coreTypes,
+ normSupertype(_hierarchy.coreTypes, superclass),
+ normSupertype(_hierarchy.coreTypes, type));
+ if (merge != null) {
+ return merge;
}
+ } else if (type == superclass) {
+ return superclass;
}
-
- List<Supertype> superclasses;
- List<Supertype> interfacesList;
- int maxInheritancePath;
-
- ClassHierarchyNode? mixedInNode;
- List<ClassHierarchyNode>? interfaceNodes;
-
- if (classBuilder.isMixinApplication) {
- mixedInNode = inferMixinApplication();
+ LibraryBuilder libraryBuilder = _libraryBuilder;
+ if (libraryBuilder is SourceLibraryBuilder) {
+ libraryBuilder.addProblem(
+ templateAmbiguousSupertypes.withArguments(
+ _name,
+ superclass.asInterfaceType,
+ type.asInterfaceType,
+ libraryBuilder.isNonNullableByDefault),
+ _fileOffset,
+ noLength,
+ _fileUri);
}
-
- if (supernode == null) {
- // This should be Object.
- superclasses = new List<Supertype>.filled(0, dummySupertype);
- interfacesList = new List<Supertype>.filled(0, dummySupertype);
- maxInheritancePath = 0;
- } else {
- maxInheritancePath = supernode.maxInheritancePath + 1;
-
- superclasses = new List<Supertype>.filled(
- supernode.superclasses.length + 1, dummySupertype);
- Supertype? supertype = classBuilder.supertypeBuilder!
- .buildSupertype(classBuilder.libraryBuilder);
- if (supertype == null) {
- // If the superclass is not an interface type we use Object instead.
- // A similar normalization is performed on [supernode] above.
- supertype =
- new Supertype(hierarchy.coreTypes.objectClass, const <DartType>[]);
- }
- superclasses.setRange(0, superclasses.length - 1,
- substSupertypes(supertype, supernode.superclasses));
- superclasses[superclasses.length - 1] = supertype;
- if (!classBuilder.libraryBuilder.isNonNullableByDefault &&
- supernode.classBuilder.libraryBuilder.isNonNullableByDefault) {
- for (int i = 0; i < superclasses.length; i++) {
- superclasses[i] = legacyErasureSupertype(superclasses[i]);
- }
- }
-
- List<TypeBuilder>? directInterfaceBuilders =
- ignoreFunction(classBuilder.interfaceBuilders);
- if (classBuilder.isMixinApplication) {
- if (directInterfaceBuilders == null) {
- directInterfaceBuilders = <TypeBuilder>[
- classBuilder.mixedInTypeBuilder!
- ];
- } else {
- directInterfaceBuilders = <TypeBuilder>[
- classBuilder.mixedInTypeBuilder!
- ]..addAll(directInterfaceBuilders);
- }
- }
-
- List<Supertype> superclassInterfaces = supernode.interfaces;
- if (superclassInterfaces.isNotEmpty) {
- superclassInterfaces = substSupertypes(supertype, superclassInterfaces);
- }
-
- if (directInterfaceBuilders != null) {
- Map<Class, Supertype> interfaces = {};
- if (superclassInterfaces.isNotEmpty) {
- for (int i = 0; i < superclassInterfaces.length; i++) {
- addInterface(interfaces, superclasses, superclassInterfaces[i]);
- }
- }
-
- for (int i = 0; i < directInterfaceBuilders.length; i++) {
- Supertype? directInterface = directInterfaceBuilders[i]
- .buildSupertype(classBuilder.libraryBuilder);
- if (directInterface != null) {
- addInterface(interfaces, superclasses, directInterface);
- ClassHierarchyNode interfaceNode =
- hierarchy.getNodeFromClass(directInterface.classNode);
- (interfaceNodes ??= []).add(interfaceNode);
-
- if (maxInheritancePath < interfaceNode.maxInheritancePath + 1) {
- maxInheritancePath = interfaceNode.maxInheritancePath + 1;
- }
-
- List<Supertype> types =
- substSupertypes(directInterface, interfaceNode.superclasses);
- for (int i = 0; i < types.length; i++) {
- addInterface(interfaces, superclasses, types[i]);
- }
- if (interfaceNode.interfaces.isNotEmpty) {
- List<Supertype> types =
- substSupertypes(directInterface, interfaceNode.interfaces);
- for (int i = 0; i < types.length; i++) {
- addInterface(interfaces, superclasses, types[i]);
- }
- }
- }
- }
- interfacesList = interfaces.values.toList();
- } else if (superclassInterfaces.isNotEmpty &&
- !classBuilder.libraryBuilder.isNonNullableByDefault &&
- supernode.classBuilder.libraryBuilder.isNonNullableByDefault) {
- Map<Class, Supertype> interfaces = {};
- for (int i = 0; i < superclassInterfaces.length; i++) {
- addInterface(interfaces, superclasses, superclassInterfaces[i]);
- }
- interfacesList = interfaces.values.toList();
- } else {
- interfacesList = superclassInterfaces;
- }
- }
-
- return new ClassHierarchyNode(classBuilder, supernode, mixedInNode,
- interfaceNodes, superclasses, interfacesList, maxInheritancePath);
+ return superclass;
}
- List<Supertype> substSupertypes(
+ List<Supertype> _substSupertypes(
Supertype supertype, List<Supertype> supertypes) {
List<TypeParameter> typeVariables = supertype.classNode.typeParameters;
if (typeVariables.isEmpty) {
- debug?.log("In ${this.classBuilder.fullNameForErrors} "
- "$supertypes aren't substed");
return supertypes;
}
Map<TypeParameter, DartType> map = <TypeParameter, DartType>{};
@@ -175,51 +81,181 @@
Supertype supertype = supertypes[i];
Supertype substituted = substitution.substituteSupertype(supertype);
if (supertype != substituted) {
- debug?.log("In ${this.classBuilder.fullNameForErrors} $supertype"
- " -> $substituted");
result ??= supertypes.toList();
result[i] = substituted;
- } else {
- debug?.log("In ${this.classBuilder.fullNameForErrors} "
- "$supertype isn't substed");
}
}
return result ?? supertypes;
}
- Supertype _resolveSupertypeConflict(Supertype type, Supertype superclass) {
- if (classBuilder.libraryBuilder.isNonNullableByDefault) {
- Supertype? merge = nnbdTopMergeSupertype(
- hierarchy.coreTypes,
- normSupertype(hierarchy.coreTypes, superclass),
- normSupertype(hierarchy.coreTypes, type));
- if (merge != null) {
- return merge;
+ /// The class Function from dart:core is supposed to be ignored when used as
+ /// an interface.
+ List<TypeBuilder>? _ignoreFunction(List<TypeBuilder>? interfaces) {
+ if (interfaces == null) return null;
+ for (int i = 0; i < interfaces!.length; i++) {
+ ClassBuilder? classBuilder = getClass(interfaces[i]);
+ if (classBuilder != null &&
+ classBuilder.cls == _hierarchy.functionClass) {
+ if (interfaces.length == 1) {
+ return null;
+ } else {
+ interfaces = interfaces.toList();
+ interfaces.removeAt(i);
+ return _ignoreFunction(interfaces);
+ }
}
- } else if (type == superclass) {
- return superclass;
}
- LibraryBuilder libraryBuilder = classBuilder.libraryBuilder;
- if (libraryBuilder is SourceLibraryBuilder) {
- libraryBuilder.addProblem(
- templateAmbiguousSupertypes.withArguments(
- classBuilder.name,
- superclass.asInterfaceType,
- type.asInterfaceType,
- libraryBuilder.isNonNullableByDefault),
- classBuilder.charOffset,
- noLength,
- classBuilder.fileUri);
+ return interfaces;
+ }
+}
+
+class ClassHierarchyNodeBuilder extends HierarchyNodeBuilder {
+ final ClassBuilder _classBuilder;
+
+ ClassHierarchyNodeBuilder(super.hierarchy, this._classBuilder);
+
+ ClassBuilder get _objectClass => _hierarchy.objectClassBuilder;
+
+ @override
+ LibraryBuilder get _libraryBuilder => _classBuilder.libraryBuilder;
+
+ @override
+ String get _name => _classBuilder.name;
+
+ @override
+ int get _fileOffset => _classBuilder.charOffset;
+
+ @override
+ Uri get _fileUri => _classBuilder.fileUri;
+
+ ClassHierarchyNode build() {
+ assert(!_classBuilder.isPatch);
+ ClassHierarchyNode? supernode;
+ if (_objectClass != _classBuilder.origin) {
+ ClassBuilder? superClassBuilder =
+ getClass(_classBuilder.supertypeBuilder!);
+ supernode =
+ _hierarchy.getNodeFromClassBuilder(superClassBuilder ?? _objectClass);
}
- return superclass;
+
+ List<Supertype> superclasses;
+ List<Supertype> interfacesList;
+ int maxInheritancePath;
+
+ ClassHierarchyNode? mixedInNode;
+ List<ClassHierarchyNode>? interfaceNodes;
+
+ if (_classBuilder.isMixinApplication) {
+ mixedInNode = _inferMixinApplication();
+ }
+
+ if (supernode == null) {
+ // This should be Object.
+ superclasses = new List<Supertype>.filled(0, dummySupertype);
+ interfacesList = new List<Supertype>.filled(0, dummySupertype);
+ maxInheritancePath = 0;
+ } else {
+ maxInheritancePath = supernode.maxInheritancePath + 1;
+
+ superclasses = new List<Supertype>.filled(
+ supernode.superclasses.length + 1, dummySupertype);
+ Supertype? supertype = _classBuilder.supertypeBuilder!
+ .buildSupertype(_classBuilder.libraryBuilder);
+ if (supertype == null) {
+ // If the superclass is not an interface type we use Object instead.
+ // A similar normalization is performed on [supernode] above.
+ supertype =
+ new Supertype(_hierarchy.coreTypes.objectClass, const <DartType>[]);
+ }
+ superclasses.setRange(0, superclasses.length - 1,
+ _substSupertypes(supertype, supernode.superclasses));
+ superclasses[superclasses.length - 1] = supertype;
+ if (!_classBuilder.libraryBuilder.isNonNullableByDefault &&
+ supernode.classBuilder.libraryBuilder.isNonNullableByDefault) {
+ for (int i = 0; i < superclasses.length; i++) {
+ superclasses[i] = legacyErasureSupertype(superclasses[i]);
+ }
+ }
+
+ List<TypeBuilder>? directInterfaceBuilders =
+ _ignoreFunction(_classBuilder.interfaceBuilders);
+ if (_classBuilder.isMixinApplication) {
+ if (directInterfaceBuilders == null) {
+ directInterfaceBuilders = <TypeBuilder>[
+ _classBuilder.mixedInTypeBuilder!
+ ];
+ } else {
+ directInterfaceBuilders = <TypeBuilder>[
+ _classBuilder.mixedInTypeBuilder!
+ ]..addAll(directInterfaceBuilders);
+ }
+ }
+
+ List<Supertype> superclassInterfaces = supernode.interfaces;
+ if (superclassInterfaces.isNotEmpty) {
+ superclassInterfaces =
+ _substSupertypes(supertype, superclassInterfaces);
+ }
+
+ if (directInterfaceBuilders != null) {
+ Map<Class, Supertype> interfaces = {};
+ if (superclassInterfaces.isNotEmpty) {
+ for (int i = 0; i < superclassInterfaces.length; i++) {
+ _addInterface(interfaces, superclasses, superclassInterfaces[i]);
+ }
+ }
+
+ for (int i = 0; i < directInterfaceBuilders.length; i++) {
+ Supertype? directInterface = directInterfaceBuilders[i]
+ .buildSupertype(_classBuilder.libraryBuilder);
+ if (directInterface != null) {
+ _addInterface(interfaces, superclasses, directInterface);
+ ClassHierarchyNode interfaceNode =
+ _hierarchy.getNodeFromClass(directInterface.classNode);
+ (interfaceNodes ??= []).add(interfaceNode);
+
+ if (maxInheritancePath < interfaceNode.maxInheritancePath + 1) {
+ maxInheritancePath = interfaceNode.maxInheritancePath + 1;
+ }
+
+ List<Supertype> types =
+ _substSupertypes(directInterface, interfaceNode.superclasses);
+ for (int i = 0; i < types.length; i++) {
+ _addInterface(interfaces, superclasses, types[i]);
+ }
+ if (interfaceNode.interfaces.isNotEmpty) {
+ List<Supertype> types =
+ _substSupertypes(directInterface, interfaceNode.interfaces);
+ for (int i = 0; i < types.length; i++) {
+ _addInterface(interfaces, superclasses, types[i]);
+ }
+ }
+ }
+ }
+ interfacesList = interfaces.values.toList();
+ } else if (superclassInterfaces.isNotEmpty &&
+ !_classBuilder.libraryBuilder.isNonNullableByDefault &&
+ supernode.classBuilder.libraryBuilder.isNonNullableByDefault) {
+ Map<Class, Supertype> interfaces = {};
+ for (int i = 0; i < superclassInterfaces.length; i++) {
+ _addInterface(interfaces, superclasses, superclassInterfaces[i]);
+ }
+ interfacesList = interfaces.values.toList();
+ } else {
+ interfacesList = superclassInterfaces;
+ }
+ }
+
+ return new ClassHierarchyNode(_classBuilder, supernode, mixedInNode,
+ interfaceNodes, superclasses, interfacesList, maxInheritancePath);
}
- void addInterface(Map<Class, Supertype> interfaces,
+ void _addInterface(Map<Class, Supertype> interfaces,
List<Supertype> superclasses, Supertype type) {
- if (!classBuilder.libraryBuilder.isNonNullableByDefault) {
+ if (!_libraryBuilder.isNonNullableByDefault) {
type = legacyErasureSupertype(type);
}
- ClassHierarchyNode node = hierarchy.getNodeFromClass(type.classNode);
+ ClassHierarchyNode node = _hierarchy.getNodeFromClass(type.classNode);
int depth = node.depth;
int myDepth = superclasses.length;
Supertype? superclass = depth < myDepth ? superclasses[depth] : null;
@@ -238,52 +274,33 @@
interfaces[type.classNode] = type;
}
- ClassHierarchyNode? inferMixinApplication() {
- Class cls = classBuilder.cls;
+ ClassHierarchyNode? _inferMixinApplication() {
+ Class cls = _classBuilder.cls;
Supertype? mixedInType = cls.mixedInType;
if (mixedInType == null) return null;
ClassHierarchyNode? mixinNode =
- hierarchy.getNodeFromClass(mixedInType.classNode);
+ _hierarchy.getNodeFromClass(mixedInType.classNode);
List<DartType> typeArguments = mixedInType.typeArguments;
if (typeArguments.isEmpty || typeArguments.first is! UnknownType) {
return mixinNode;
}
new BuilderMixinInferrer(
- classBuilder,
- hierarchy.coreTypes,
+ _classBuilder,
+ _hierarchy.coreTypes,
new TypeBuilderConstraintGatherer(
- hierarchy, mixedInType.classNode.typeParameters,
+ _hierarchy, mixedInType.classNode.typeParameters,
isNonNullableByDefault:
cls.enclosingLibrary.isNonNullableByDefault))
.infer(cls);
List<TypeBuilder> inferredArguments = new List<TypeBuilder>.generate(
typeArguments.length,
- (int i) => hierarchy.loader.computeTypeBuilder(typeArguments[i]),
+ (int i) => _hierarchy.loader.computeTypeBuilder(typeArguments[i]),
growable: false);
NamedTypeBuilder mixedInTypeBuilder =
- classBuilder.mixedInTypeBuilder as NamedTypeBuilder;
+ _classBuilder.mixedInTypeBuilder as NamedTypeBuilder;
mixedInTypeBuilder.arguments = inferredArguments;
return mixinNode;
}
-
- /// The class Function from dart:core is supposed to be ignored when used as
- /// an interface.
- List<TypeBuilder>? ignoreFunction(List<TypeBuilder>? interfaces) {
- if (interfaces == null) return null;
- for (int i = 0; i < interfaces!.length; i++) {
- ClassBuilder? classBuilder = getClass(interfaces[i]);
- if (classBuilder != null && classBuilder.cls == hierarchy.functionClass) {
- if (interfaces.length == 1) {
- return null;
- } else {
- interfaces = interfaces.toList();
- interfaces.removeAt(i);
- return ignoreFunction(interfaces);
- }
- }
- }
- return interfaces;
- }
}
class ClassHierarchyNode {
@@ -385,6 +402,209 @@
}
}
+class ExtensionTypeHierarchyNodeBuilder extends HierarchyNodeBuilder {
+ final InlineClassBuilder _extensionTypeBuilder;
+
+ ExtensionTypeHierarchyNodeBuilder(
+ super._hierarchy, this._extensionTypeBuilder);
+
+ @override
+ LibraryBuilder get _libraryBuilder => _extensionTypeBuilder.libraryBuilder;
+
+ @override
+ String get _name => _extensionTypeBuilder.name;
+
+ @override
+ int get _fileOffset => _extensionTypeBuilder.charOffset;
+
+ @override
+ Uri get _fileUri => _extensionTypeBuilder.fileUri;
+
+ ExtensionTypeHierarchyNode build() {
+ assert(!_extensionTypeBuilder.isPatch);
+ Map<Class, Supertype> superclasses = {};
+ Map<InlineClass, InlineType> superExtensionTypes = {};
+ List<ClassHierarchyNode>? superclassNodes;
+ List<ExtensionTypeHierarchyNode>? superExtensionTypeNodes;
+ int maxInheritancePath = 1;
+
+ List<TypeBuilder>? directInterfaceBuilders =
+ _ignoreFunction(_extensionTypeBuilder.interfaceBuilders);
+ if (directInterfaceBuilders != null) {
+ for (int i = 0; i < directInterfaceBuilders.length; i++) {
+ DartType directInterface = directInterfaceBuilders[i]
+ .build(_extensionTypeBuilder.libraryBuilder, TypeUse.superType);
+ if (directInterface is InterfaceType) {
+ Supertype supertype = new Supertype.byReference(
+ directInterface.classReference, directInterface.typeArguments);
+ _addSuperClass(superclasses, supertype);
+ ClassHierarchyNode interfaceNode =
+ _hierarchy.getNodeFromClass(directInterface.classNode);
+ (superclassNodes ??= []).add(interfaceNode);
+
+ if (maxInheritancePath < interfaceNode.maxInheritancePath + 1) {
+ maxInheritancePath = interfaceNode.maxInheritancePath + 1;
+ }
+
+ List<Supertype> types =
+ _substSupertypes(supertype, interfaceNode.superclasses);
+ for (int i = 0; i < types.length; i++) {
+ _addSuperClass(superclasses, types[i]);
+ }
+ if (interfaceNode.interfaces.isNotEmpty) {
+ List<Supertype> types =
+ _substSupertypes(supertype, interfaceNode.interfaces);
+ for (int i = 0; i < types.length; i++) {
+ _addSuperClass(superclasses, types[i]);
+ }
+ }
+ } else if (directInterface is InlineType) {
+ _addSuperExtensionType(superExtensionTypes, directInterface);
+ ExtensionTypeHierarchyNode interfaceNode =
+ _hierarchy.getNodeFromExtensionType(directInterface.inlineClass);
+ (superExtensionTypeNodes ??= []).add(interfaceNode);
+
+ if (maxInheritancePath < interfaceNode.maxInheritancePath + 1) {
+ maxInheritancePath = interfaceNode.maxInheritancePath + 1;
+ }
+
+ List<InlineType> types = _substSuperExtensionTypes(
+ directInterface, interfaceNode.superExtensionTypes);
+ for (int i = 0; i < types.length; i++) {
+ _addSuperExtensionType(superExtensionTypes, types[i]);
+ }
+ if (interfaceNode.superExtensionTypes.isNotEmpty) {
+ List<InlineType> types = _substSuperExtensionTypes(
+ directInterface, interfaceNode.superExtensionTypes);
+ for (int i = 0; i < types.length; i++) {
+ _addSuperExtensionType(superExtensionTypes, types[i]);
+ }
+ }
+ }
+ }
+ }
+
+ return new ExtensionTypeHierarchyNode(
+ _extensionTypeBuilder,
+ superclasses.values.toList(),
+ superExtensionTypes.values.toList(),
+ superclassNodes,
+ superExtensionTypeNodes,
+ maxInheritancePath);
+ }
+
+ void _addSuperClass(Map<Class, Supertype> superClasses, Supertype type) {
+ if (!_libraryBuilder.isNonNullableByDefault) {
+ type = legacyErasureSupertype(type);
+ }
+ Supertype? interface = superClasses[type.classNode];
+ if (interface != null) {
+ // This is a potential conflict.
+ superClasses[type.classNode] = _resolveSupertypeConflict(type, interface);
+ return;
+ }
+ superClasses[type.classNode] = type;
+ }
+
+ InlineType _resolveSuperExtensionTypeConflict(
+ InlineType type, InlineType superclass) {
+ if (_libraryBuilder.isNonNullableByDefault) {
+ DartType? merge = nnbdTopMerge(
+ _hierarchy.coreTypes,
+ norm(_hierarchy.coreTypes, superclass),
+ norm(_hierarchy.coreTypes, type));
+ if (merge != null) {
+ return merge as InlineType;
+ }
+ } else if (type == superclass) {
+ return superclass;
+ }
+ LibraryBuilder libraryBuilder = _libraryBuilder;
+ if (libraryBuilder is SourceLibraryBuilder) {
+ libraryBuilder.addProblem(
+ templateAmbiguousSupertypes.withArguments(
+ _name, superclass, type, libraryBuilder.isNonNullableByDefault),
+ _fileOffset,
+ noLength,
+ _fileUri);
+ }
+ return superclass;
+ }
+
+ void _addSuperExtensionType(
+ Map<InlineClass, InlineType> interfaces, InlineType type) {
+ if (!_libraryBuilder.isNonNullableByDefault) {
+ type = legacyErasure(type) as InlineType;
+ }
+ InlineType? interface = interfaces[type.inlineClass];
+ if (interface != null) {
+ // This is a potential conflict.
+ interfaces[type.inlineClass] =
+ _resolveSuperExtensionTypeConflict(type, interface);
+ return;
+ }
+ interfaces[type.inlineClass] = type;
+ }
+
+ List<InlineType> _substSuperExtensionTypes(
+ InlineType superExtensionType, List<InlineType> superExtensionTypes) {
+ List<TypeParameter> typeVariables =
+ superExtensionType.inlineClass.typeParameters;
+ if (typeVariables.isEmpty) {
+ return superExtensionTypes;
+ }
+ Map<TypeParameter, DartType> map = <TypeParameter, DartType>{};
+ List<DartType> arguments = superExtensionType.typeArguments;
+ for (int i = 0; i < typeVariables.length; i++) {
+ map[typeVariables[i]] = arguments[i];
+ }
+ Substitution substitution = Substitution.fromMap(map);
+ List<InlineType>? result;
+ for (int i = 0; i < superExtensionTypes.length; i++) {
+ InlineType supertype = superExtensionTypes[i];
+ InlineType substituted =
+ substitution.substituteType(supertype) as InlineType;
+ if (supertype != substituted) {
+ result ??= superExtensionTypes.toList();
+ result[i] = substituted;
+ }
+ }
+ return result ?? superExtensionTypes;
+ }
+}
+
+class ExtensionTypeHierarchyNode {
+ /// The extension type corresponding to this hierarchy node.
+ final InlineClassBuilder extensionTypeBuilder;
+
+ /// The list of all classes implemented by [extensionTypeBuilder] and its
+ /// superclasses.
+ final List<Supertype> superclasses;
+
+ /// The list of all extension types implemented by [extensionTypeBuilder]
+ /// and its super extension types.
+ final List<InlineType> superExtensionTypes;
+
+ /// The [ClassHierarchyNode]s for the direct superclasses of
+ /// [extensionTypeBuilder].
+ final List<ClassHierarchyNode>? directSuperclassNodes;
+
+ /// The [ExtensionTypeHierarchyNode]s for the direct super extension types of
+ /// [extensionTypeBuilder].
+ final List<ExtensionTypeHierarchyNode>? directSuperExtensionTypeNodes;
+
+ /// The longest inheritance path from [extensionTypeBuilder] to `Object`.
+ final int maxInheritancePath;
+
+ ExtensionTypeHierarchyNode(
+ this.extensionTypeBuilder,
+ this.superclasses,
+ this.superExtensionTypes,
+ this.directSuperclassNodes,
+ this.directSuperExtensionTypeNodes,
+ this.maxInheritancePath);
+}
+
ClassBuilder? getClass(TypeBuilder type) {
Builder? declaration = type.declaration;
if (declaration is TypeAliasBuilder) {
@@ -394,11 +614,3 @@
}
return declaration is ClassBuilder ? declaration : null;
}
-
-const DebugLogger? debug =
- const bool.fromEnvironment("debug.hierarchy") ? const DebugLogger() : null;
-
-class DebugLogger {
- const DebugLogger();
- void log(Object message) => print(message);
-}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 525ab30..cfc72da 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -432,7 +432,6 @@
benchmarker?.enterPhase(BenchmarkPhases.outline_checkSemantics);
List<SourceClassBuilder>? sortedSourceClassBuilders;
- // ignore: unused_local_variable
List<SourceInlineClassBuilder>? sortedSourceExtensionTypeBuilders;
(sortedSourceClassBuilders, sortedSourceExtensionTypeBuilders) =
loader.checkClassCycles(objectClassBuilder);
@@ -459,7 +458,8 @@
computeCoreTypes();
benchmarker?.enterPhase(BenchmarkPhases.outline_buildClassHierarchy);
- loader.buildClassHierarchy(sortedSourceClassBuilders, objectClassBuilder);
+ loader.buildClassHierarchy(sortedSourceClassBuilders,
+ sortedSourceExtensionTypeBuilders, objectClassBuilder);
benchmarker?.enterPhase(BenchmarkPhases.outline_checkSupertypes);
loader.checkSupertypes(sortedSourceClassBuilders, objectClass, enumClass,
diff --git a/pkg/front_end/lib/src/fasta/loader.dart b/pkg/front_end/lib/src/fasta/loader.dart
index 116eb5c..1c9fd94 100644
--- a/pkg/front_end/lib/src/fasta/loader.dart
+++ b/pkg/front_end/lib/src/fasta/loader.dart
@@ -6,9 +6,10 @@
import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
-import 'package:kernel/ast.dart' show Class, DartType;
+import 'package:kernel/ast.dart' show Class, DartType, InlineClass;
import 'builder/class_builder.dart';
+import 'builder/inline_class_builder.dart';
import 'builder/library_builder.dart';
import 'builder/type_builder.dart';
@@ -35,6 +36,9 @@
ClassBuilder computeClassBuilderFromTargetClass(Class cls);
+ InlineClassBuilder computeExtensionTypeBuilderFromTargetExtensionType(
+ InlineClass extensionType);
+
TypeBuilder computeTypeBuilder(DartType type);
LibraryBuilder get coreLibrary;
diff --git a/pkg/front_end/lib/src/fasta/source/source_inline_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_inline_class_builder.dart
index efb754f..f4db5a4 100644
--- a/pkg/front_end/lib/src/fasta/source/source_inline_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_inline_class_builder.dart
@@ -51,6 +51,7 @@
@override
final List<TypeVariableBuilder>? typeParameters;
+ @override
List<TypeBuilder>? interfaceBuilders;
final SourceFieldBuilder? representationFieldBuilder;
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 706818b..c8f7eb1 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -44,6 +44,7 @@
import '../builder/builder.dart';
import '../builder/class_builder.dart';
import '../builder/extension_builder.dart';
+import '../builder/inline_class_builder.dart';
import '../builder/invalid_type_declaration_builder.dart';
import '../builder/library_builder.dart';
import '../builder/member_builder.dart';
@@ -2817,10 +2818,12 @@
}
void buildClassHierarchy(
- List<SourceClassBuilder> sourceClasses, ClassBuilder objectClass) {
+ List<SourceClassBuilder> sourceClasses,
+ List<SourceInlineClassBuilder> sourceExtensionTypes,
+ ClassBuilder objectClass) {
ClassHierarchyBuilder hierarchyBuilder = _hierarchyBuilder =
ClassHierarchyBuilder.build(
- objectClass, sourceClasses, this, coreTypes);
+ objectClass, sourceClasses, sourceExtensionTypes, this, coreTypes);
typeInferenceEngine.hierarchyBuilder = hierarchyBuilder;
ticker.logMs("Built class hierarchy");
}
@@ -3038,6 +3041,19 @@
return library.lookupLocalMember(cls.name, required: true) as ClassBuilder;
}
+ @override
+ InlineClassBuilder computeExtensionTypeBuilderFromTargetExtensionType(
+ InlineClass extensionType) {
+ Library kernelLibrary = extensionType.enclosingLibrary;
+ LibraryBuilder? library = lookupLibraryBuilder(kernelLibrary.importUri);
+ if (library == null) {
+ return target.dillTarget.loader
+ .computeExtensionTypeBuilderFromTargetExtensionType(extensionType);
+ }
+ return library.lookupLocalMember(extensionType.name, required: true)
+ as InlineClassBuilder;
+ }
+
late TypeBuilderComputer _typeBuilderComputer = new TypeBuilderComputer(this);
@override
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index 38eb0fb..3158613 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -2606,7 +2606,7 @@
KernelTarget target = result.sourceTarget;
ClassHierarchyBuilder hierarchy = target.loader.hierarchyBuilder;
StringBuffer sb = new StringBuffer();
- for (ClassHierarchyNode node in hierarchy.nodes.values) {
+ for (ClassHierarchyNode node in hierarchy.classNodes.values) {
sb.writeln(node);
}
return context.match<ComponentResult>(
diff --git a/pkg/front_end/test/fasta/types/dill_hierarchy_test.dart b/pkg/front_end/test/fasta/types/dill_hierarchy_test.dart
index eed27c8..639ee03 100644
--- a/pkg/front_end/test/fasta/types/dill_hierarchy_test.dart
+++ b/pkg/front_end/test/fasta/types/dill_hierarchy_test.dart
@@ -106,6 +106,6 @@
hierarchy.getNodeFromClass(cls);
}
Expect.stringEquals(
- expectedHierarchy, hierarchy.nodes.values.join("\n"));
+ expectedHierarchy, hierarchy.classNodes.values.join("\n"));
}));
}
diff --git a/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart b/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart
new file mode 100644
index 0000000..81031de
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart
@@ -0,0 +1,13 @@
+// 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 a
+// BSD-style license that can be found in the LICENSE file.
+
+extension type A<T>(int it) {}
+
+extension type B<T>(int it) implements A<T> {}
+
+extension type C<T>(int it) implements A<T> {}
+
+extension type D(int it) implements A<int>, B<String> {}
+
+extension type E(int it) implements B<int>, C<String> {}
diff --git a/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.strong.expect b/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.strong.expect
new file mode 100644
index 0000000..aa8e3c36
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.strong.expect
@@ -0,0 +1,65 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart:11:16: Error: 'D' can't implement both 'A<int>' and 'A<String>'
+// extension type D(int it) implements A<int>, B<String> {}
+// ^
+//
+// pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart:13:16: Error: 'E' can't implement both 'A<int>' and 'A<String>'
+// extension type E(int it) implements B<int>, C<String> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+inline class A<T extends core::Object? = dynamic> /* declaredRepresentationType = core::int */ {
+ constructor • = self::A|;
+ tearoff • = self::A|_#new#tearOff;
+}
+inline class B<T extends core::Object? = dynamic> /* declaredRepresentationType = core::int */ implements self::A<T%> {
+ constructor • = self::B|;
+ tearoff • = self::B|_#new#tearOff;
+}
+inline class C<T extends core::Object? = dynamic> /* declaredRepresentationType = core::int */ implements self::A<T%> {
+ constructor • = self::C|;
+ tearoff • = self::C|_#new#tearOff;
+}
+inline class D /* declaredRepresentationType = core::int */ implements self::A<core::int>, self::B<core::String> {
+ constructor • = self::D|;
+ tearoff • = self::D|_#new#tearOff;
+}
+inline class E /* declaredRepresentationType = core::int */ implements self::B<core::int>, self::C<core::String> {
+ constructor • = self::E|;
+ tearoff • = self::E|_#new#tearOff;
+}
+static inline-class-member method A|<T extends core::Object? = dynamic>(dynamic it) → self::A<self::A|::T%> {
+ lowered final self::A<self::A|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method A|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::A<self::A|_#new#tearOff::T%>
+ return self::A|<self::A|_#new#tearOff::T%>(it);
+static inline-class-member method B|<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|::T%> {
+ lowered final self::B<self::B|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method B|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|_#new#tearOff::T%>
+ return self::B|<self::B|_#new#tearOff::T%>(it);
+static inline-class-member method C|<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|::T%> {
+ lowered final self::C<self::C|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method C|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|_#new#tearOff::T%>
+ return self::C|<self::C|_#new#tearOff::T%>(it);
+static inline-class-member method D|(dynamic it) → self::D {
+ lowered final self::D #this = it;
+ return #this;
+}
+static inline-class-member method D|_#new#tearOff(dynamic it) → self::D
+ return self::D|(it);
+static inline-class-member method E|(dynamic it) → self::E {
+ lowered final self::E #this = it;
+ return #this;
+}
+static inline-class-member method E|_#new#tearOff(dynamic it) → self::E
+ return self::E|(it);
diff --git a/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.strong.transformed.expect b/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.strong.transformed.expect
new file mode 100644
index 0000000..aa8e3c36
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.strong.transformed.expect
@@ -0,0 +1,65 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart:11:16: Error: 'D' can't implement both 'A<int>' and 'A<String>'
+// extension type D(int it) implements A<int>, B<String> {}
+// ^
+//
+// pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart:13:16: Error: 'E' can't implement both 'A<int>' and 'A<String>'
+// extension type E(int it) implements B<int>, C<String> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+inline class A<T extends core::Object? = dynamic> /* declaredRepresentationType = core::int */ {
+ constructor • = self::A|;
+ tearoff • = self::A|_#new#tearOff;
+}
+inline class B<T extends core::Object? = dynamic> /* declaredRepresentationType = core::int */ implements self::A<T%> {
+ constructor • = self::B|;
+ tearoff • = self::B|_#new#tearOff;
+}
+inline class C<T extends core::Object? = dynamic> /* declaredRepresentationType = core::int */ implements self::A<T%> {
+ constructor • = self::C|;
+ tearoff • = self::C|_#new#tearOff;
+}
+inline class D /* declaredRepresentationType = core::int */ implements self::A<core::int>, self::B<core::String> {
+ constructor • = self::D|;
+ tearoff • = self::D|_#new#tearOff;
+}
+inline class E /* declaredRepresentationType = core::int */ implements self::B<core::int>, self::C<core::String> {
+ constructor • = self::E|;
+ tearoff • = self::E|_#new#tearOff;
+}
+static inline-class-member method A|<T extends core::Object? = dynamic>(dynamic it) → self::A<self::A|::T%> {
+ lowered final self::A<self::A|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method A|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::A<self::A|_#new#tearOff::T%>
+ return self::A|<self::A|_#new#tearOff::T%>(it);
+static inline-class-member method B|<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|::T%> {
+ lowered final self::B<self::B|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method B|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|_#new#tearOff::T%>
+ return self::B|<self::B|_#new#tearOff::T%>(it);
+static inline-class-member method C|<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|::T%> {
+ lowered final self::C<self::C|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method C|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|_#new#tearOff::T%>
+ return self::C|<self::C|_#new#tearOff::T%>(it);
+static inline-class-member method D|(dynamic it) → self::D {
+ lowered final self::D #this = it;
+ return #this;
+}
+static inline-class-member method D|_#new#tearOff(dynamic it) → self::D
+ return self::D|(it);
+static inline-class-member method E|(dynamic it) → self::E {
+ lowered final self::E #this = it;
+ return #this;
+}
+static inline-class-member method E|_#new#tearOff(dynamic it) → self::E
+ return self::E|(it);
diff --git a/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.textual_outline.expect b/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.textual_outline.expect
new file mode 100644
index 0000000..1c578a5
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.textual_outline.expect
@@ -0,0 +1 @@
+extension type A<T>(int it) {} extension type B<T>(int it) implements A<T> {} extension type C<T>(int it) implements A<T> {} extension type D(int it) implements A<int>, B<String> {} extension type E(int it) implements B<int>, C<String> {}
diff --git a/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.weak.expect b/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.weak.expect
new file mode 100644
index 0000000..aa8e3c36
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.weak.expect
@@ -0,0 +1,65 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart:11:16: Error: 'D' can't implement both 'A<int>' and 'A<String>'
+// extension type D(int it) implements A<int>, B<String> {}
+// ^
+//
+// pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart:13:16: Error: 'E' can't implement both 'A<int>' and 'A<String>'
+// extension type E(int it) implements B<int>, C<String> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+inline class A<T extends core::Object? = dynamic> /* declaredRepresentationType = core::int */ {
+ constructor • = self::A|;
+ tearoff • = self::A|_#new#tearOff;
+}
+inline class B<T extends core::Object? = dynamic> /* declaredRepresentationType = core::int */ implements self::A<T%> {
+ constructor • = self::B|;
+ tearoff • = self::B|_#new#tearOff;
+}
+inline class C<T extends core::Object? = dynamic> /* declaredRepresentationType = core::int */ implements self::A<T%> {
+ constructor • = self::C|;
+ tearoff • = self::C|_#new#tearOff;
+}
+inline class D /* declaredRepresentationType = core::int */ implements self::A<core::int>, self::B<core::String> {
+ constructor • = self::D|;
+ tearoff • = self::D|_#new#tearOff;
+}
+inline class E /* declaredRepresentationType = core::int */ implements self::B<core::int>, self::C<core::String> {
+ constructor • = self::E|;
+ tearoff • = self::E|_#new#tearOff;
+}
+static inline-class-member method A|<T extends core::Object? = dynamic>(dynamic it) → self::A<self::A|::T%> {
+ lowered final self::A<self::A|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method A|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::A<self::A|_#new#tearOff::T%>
+ return self::A|<self::A|_#new#tearOff::T%>(it);
+static inline-class-member method B|<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|::T%> {
+ lowered final self::B<self::B|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method B|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|_#new#tearOff::T%>
+ return self::B|<self::B|_#new#tearOff::T%>(it);
+static inline-class-member method C|<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|::T%> {
+ lowered final self::C<self::C|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method C|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|_#new#tearOff::T%>
+ return self::C|<self::C|_#new#tearOff::T%>(it);
+static inline-class-member method D|(dynamic it) → self::D {
+ lowered final self::D #this = it;
+ return #this;
+}
+static inline-class-member method D|_#new#tearOff(dynamic it) → self::D
+ return self::D|(it);
+static inline-class-member method E|(dynamic it) → self::E {
+ lowered final self::E #this = it;
+ return #this;
+}
+static inline-class-member method E|_#new#tearOff(dynamic it) → self::E
+ return self::E|(it);
diff --git a/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.weak.modular.expect b/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.weak.modular.expect
new file mode 100644
index 0000000..aa8e3c36
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.weak.modular.expect
@@ -0,0 +1,65 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart:11:16: Error: 'D' can't implement both 'A<int>' and 'A<String>'
+// extension type D(int it) implements A<int>, B<String> {}
+// ^
+//
+// pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart:13:16: Error: 'E' can't implement both 'A<int>' and 'A<String>'
+// extension type E(int it) implements B<int>, C<String> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+inline class A<T extends core::Object? = dynamic> /* declaredRepresentationType = core::int */ {
+ constructor • = self::A|;
+ tearoff • = self::A|_#new#tearOff;
+}
+inline class B<T extends core::Object? = dynamic> /* declaredRepresentationType = core::int */ implements self::A<T%> {
+ constructor • = self::B|;
+ tearoff • = self::B|_#new#tearOff;
+}
+inline class C<T extends core::Object? = dynamic> /* declaredRepresentationType = core::int */ implements self::A<T%> {
+ constructor • = self::C|;
+ tearoff • = self::C|_#new#tearOff;
+}
+inline class D /* declaredRepresentationType = core::int */ implements self::A<core::int>, self::B<core::String> {
+ constructor • = self::D|;
+ tearoff • = self::D|_#new#tearOff;
+}
+inline class E /* declaredRepresentationType = core::int */ implements self::B<core::int>, self::C<core::String> {
+ constructor • = self::E|;
+ tearoff • = self::E|_#new#tearOff;
+}
+static inline-class-member method A|<T extends core::Object? = dynamic>(dynamic it) → self::A<self::A|::T%> {
+ lowered final self::A<self::A|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method A|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::A<self::A|_#new#tearOff::T%>
+ return self::A|<self::A|_#new#tearOff::T%>(it);
+static inline-class-member method B|<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|::T%> {
+ lowered final self::B<self::B|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method B|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|_#new#tearOff::T%>
+ return self::B|<self::B|_#new#tearOff::T%>(it);
+static inline-class-member method C|<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|::T%> {
+ lowered final self::C<self::C|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method C|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|_#new#tearOff::T%>
+ return self::C|<self::C|_#new#tearOff::T%>(it);
+static inline-class-member method D|(dynamic it) → self::D {
+ lowered final self::D #this = it;
+ return #this;
+}
+static inline-class-member method D|_#new#tearOff(dynamic it) → self::D
+ return self::D|(it);
+static inline-class-member method E|(dynamic it) → self::E {
+ lowered final self::E #this = it;
+ return #this;
+}
+static inline-class-member method E|_#new#tearOff(dynamic it) → self::E
+ return self::E|(it);
diff --git a/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.weak.outline.expect b/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.weak.outline.expect
new file mode 100644
index 0000000..b848d6b
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.weak.outline.expect
@@ -0,0 +1,55 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart:11:16: Error: 'D' can't implement both 'A<int>' and 'A<String>'
+// extension type D(int it) implements A<int>, B<String> {}
+// ^
+//
+// pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart:13:16: Error: 'E' can't implement both 'A<int>' and 'A<String>'
+// extension type E(int it) implements B<int>, C<String> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+inline class A<T extends core::Object? = dynamic> /* declaredRepresentationType = core::int */ {
+ constructor • = self::A|;
+ tearoff • = self::A|_#new#tearOff;
+}
+inline class B<T extends core::Object? = dynamic> /* declaredRepresentationType = core::int */ implements self::A<T%> {
+ constructor • = self::B|;
+ tearoff • = self::B|_#new#tearOff;
+}
+inline class C<T extends core::Object? = dynamic> /* declaredRepresentationType = core::int */ implements self::A<T%> {
+ constructor • = self::C|;
+ tearoff • = self::C|_#new#tearOff;
+}
+inline class D /* declaredRepresentationType = core::int */ implements self::A<core::int>, self::B<core::String> {
+ constructor • = self::D|;
+ tearoff • = self::D|_#new#tearOff;
+}
+inline class E /* declaredRepresentationType = core::int */ implements self::B<core::int>, self::C<core::String> {
+ constructor • = self::E|;
+ tearoff • = self::E|_#new#tearOff;
+}
+static inline-class-member method A|<T extends core::Object? = dynamic>(dynamic it) → self::A<self::A|::T%>
+ ;
+static inline-class-member method A|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::A<self::A|_#new#tearOff::T%>
+ return self::A|<self::A|_#new#tearOff::T%>(it);
+static inline-class-member method B|<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|::T%>
+ ;
+static inline-class-member method B|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|_#new#tearOff::T%>
+ return self::B|<self::B|_#new#tearOff::T%>(it);
+static inline-class-member method C|<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|::T%>
+ ;
+static inline-class-member method C|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|_#new#tearOff::T%>
+ return self::C|<self::C|_#new#tearOff::T%>(it);
+static inline-class-member method D|(dynamic it) → self::D
+ ;
+static inline-class-member method D|_#new#tearOff(dynamic it) → self::D
+ return self::D|(it);
+static inline-class-member method E|(dynamic it) → self::E
+ ;
+static inline-class-member method E|_#new#tearOff(dynamic it) → self::E
+ return self::E|(it);
diff --git a/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.weak.transformed.expect b/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.weak.transformed.expect
new file mode 100644
index 0000000..aa8e3c36
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart.weak.transformed.expect
@@ -0,0 +1,65 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart:11:16: Error: 'D' can't implement both 'A<int>' and 'A<String>'
+// extension type D(int it) implements A<int>, B<String> {}
+// ^
+//
+// pkg/front_end/testcases/inline_class/extension_types/super_extension_type_conflict.dart:13:16: Error: 'E' can't implement both 'A<int>' and 'A<String>'
+// extension type E(int it) implements B<int>, C<String> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+inline class A<T extends core::Object? = dynamic> /* declaredRepresentationType = core::int */ {
+ constructor • = self::A|;
+ tearoff • = self::A|_#new#tearOff;
+}
+inline class B<T extends core::Object? = dynamic> /* declaredRepresentationType = core::int */ implements self::A<T%> {
+ constructor • = self::B|;
+ tearoff • = self::B|_#new#tearOff;
+}
+inline class C<T extends core::Object? = dynamic> /* declaredRepresentationType = core::int */ implements self::A<T%> {
+ constructor • = self::C|;
+ tearoff • = self::C|_#new#tearOff;
+}
+inline class D /* declaredRepresentationType = core::int */ implements self::A<core::int>, self::B<core::String> {
+ constructor • = self::D|;
+ tearoff • = self::D|_#new#tearOff;
+}
+inline class E /* declaredRepresentationType = core::int */ implements self::B<core::int>, self::C<core::String> {
+ constructor • = self::E|;
+ tearoff • = self::E|_#new#tearOff;
+}
+static inline-class-member method A|<T extends core::Object? = dynamic>(dynamic it) → self::A<self::A|::T%> {
+ lowered final self::A<self::A|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method A|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::A<self::A|_#new#tearOff::T%>
+ return self::A|<self::A|_#new#tearOff::T%>(it);
+static inline-class-member method B|<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|::T%> {
+ lowered final self::B<self::B|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method B|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|_#new#tearOff::T%>
+ return self::B|<self::B|_#new#tearOff::T%>(it);
+static inline-class-member method C|<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|::T%> {
+ lowered final self::C<self::C|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method C|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|_#new#tearOff::T%>
+ return self::C|<self::C|_#new#tearOff::T%>(it);
+static inline-class-member method D|(dynamic it) → self::D {
+ lowered final self::D #this = it;
+ return #this;
+}
+static inline-class-member method D|_#new#tearOff(dynamic it) → self::D
+ return self::D|(it);
+static inline-class-member method E|(dynamic it) → self::E {
+ lowered final self::E #this = it;
+ return #this;
+}
+static inline-class-member method E|_#new#tearOff(dynamic it) → self::E
+ return self::E|(it);
diff --git a/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart b/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart
new file mode 100644
index 0000000..7025596
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart
@@ -0,0 +1,13 @@
+// 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 a
+// BSD-style license that can be found in the LICENSE file.
+
+class A<T> {}
+
+extension type B<T>(A<T> it) implements A<T> {}
+
+extension type C<T>(A<T> it) implements C<T> {}
+
+extension type D(A<Never> it) implements A<int>, B<String> {}
+
+extension type E(A<Never> it) implements B<int>, C<String> {}
diff --git a/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.strong.expect b/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.strong.expect
new file mode 100644
index 0000000..4b905a6
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.strong.expect
@@ -0,0 +1,60 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart:9:16: Error: 'C' is a supertype of itself.
+// extension type C<T>(A<T> it) implements C<T> {}
+// ^
+//
+// pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart:13:16: Error: 'E' is a supertype of itself.
+// extension type E(A<Never> it) implements B<int>, C<String> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T%>
+ : super core::Object::•()
+ ;
+}
+inline class B<T extends core::Object? = dynamic> /* declaredRepresentationType = self::A<T%> */ {
+ constructor • = self::B|;
+ tearoff • = self::B|_#new#tearOff;
+}
+inline class C<T extends core::Object? = dynamic> /* declaredRepresentationType = self::A<T%> */ {
+ constructor • = self::C|;
+ tearoff • = self::C|_#new#tearOff;
+}
+inline class D /* declaredRepresentationType = self::A<Never> */ implements self::B<core::String> {
+ constructor • = self::D|;
+ tearoff • = self::D|_#new#tearOff;
+}
+inline class E /* declaredRepresentationType = self::A<Never> */ {
+ constructor • = self::E|;
+ tearoff • = self::E|_#new#tearOff;
+}
+static inline-class-member method B|<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|::T%> {
+ lowered final self::B<self::B|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method B|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|_#new#tearOff::T%>
+ return self::B|<self::B|_#new#tearOff::T%>(it);
+static inline-class-member method C|<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|::T%> {
+ lowered final self::C<self::C|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method C|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|_#new#tearOff::T%>
+ return self::C|<self::C|_#new#tearOff::T%>(it);
+static inline-class-member method D|(dynamic it) → self::D {
+ lowered final self::D #this = it;
+ return #this;
+}
+static inline-class-member method D|_#new#tearOff(dynamic it) → self::D
+ return self::D|(it);
+static inline-class-member method E|(dynamic it) → self::E {
+ lowered final self::E #this = it;
+ return #this;
+}
+static inline-class-member method E|_#new#tearOff(dynamic it) → self::E
+ return self::E|(it);
diff --git a/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.strong.transformed.expect b/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.strong.transformed.expect
new file mode 100644
index 0000000..4b905a6
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.strong.transformed.expect
@@ -0,0 +1,60 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart:9:16: Error: 'C' is a supertype of itself.
+// extension type C<T>(A<T> it) implements C<T> {}
+// ^
+//
+// pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart:13:16: Error: 'E' is a supertype of itself.
+// extension type E(A<Never> it) implements B<int>, C<String> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T%>
+ : super core::Object::•()
+ ;
+}
+inline class B<T extends core::Object? = dynamic> /* declaredRepresentationType = self::A<T%> */ {
+ constructor • = self::B|;
+ tearoff • = self::B|_#new#tearOff;
+}
+inline class C<T extends core::Object? = dynamic> /* declaredRepresentationType = self::A<T%> */ {
+ constructor • = self::C|;
+ tearoff • = self::C|_#new#tearOff;
+}
+inline class D /* declaredRepresentationType = self::A<Never> */ implements self::B<core::String> {
+ constructor • = self::D|;
+ tearoff • = self::D|_#new#tearOff;
+}
+inline class E /* declaredRepresentationType = self::A<Never> */ {
+ constructor • = self::E|;
+ tearoff • = self::E|_#new#tearOff;
+}
+static inline-class-member method B|<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|::T%> {
+ lowered final self::B<self::B|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method B|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|_#new#tearOff::T%>
+ return self::B|<self::B|_#new#tearOff::T%>(it);
+static inline-class-member method C|<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|::T%> {
+ lowered final self::C<self::C|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method C|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|_#new#tearOff::T%>
+ return self::C|<self::C|_#new#tearOff::T%>(it);
+static inline-class-member method D|(dynamic it) → self::D {
+ lowered final self::D #this = it;
+ return #this;
+}
+static inline-class-member method D|_#new#tearOff(dynamic it) → self::D
+ return self::D|(it);
+static inline-class-member method E|(dynamic it) → self::E {
+ lowered final self::E #this = it;
+ return #this;
+}
+static inline-class-member method E|_#new#tearOff(dynamic it) → self::E
+ return self::E|(it);
diff --git a/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.textual_outline.expect b/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.textual_outline.expect
new file mode 100644
index 0000000..3066c1a1
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.textual_outline.expect
@@ -0,0 +1,2 @@
+class A<T> {}
+extension type B<T>(A<T> it) implements A<T> {} extension type C<T>(A<T> it) implements C<T> {} extension type D(A<Never> it) implements A<int>, B<String> {} extension type E(A<Never> it) implements B<int>, C<String> {}
diff --git a/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.weak.expect b/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.weak.expect
new file mode 100644
index 0000000..4b905a6
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.weak.expect
@@ -0,0 +1,60 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart:9:16: Error: 'C' is a supertype of itself.
+// extension type C<T>(A<T> it) implements C<T> {}
+// ^
+//
+// pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart:13:16: Error: 'E' is a supertype of itself.
+// extension type E(A<Never> it) implements B<int>, C<String> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T%>
+ : super core::Object::•()
+ ;
+}
+inline class B<T extends core::Object? = dynamic> /* declaredRepresentationType = self::A<T%> */ {
+ constructor • = self::B|;
+ tearoff • = self::B|_#new#tearOff;
+}
+inline class C<T extends core::Object? = dynamic> /* declaredRepresentationType = self::A<T%> */ {
+ constructor • = self::C|;
+ tearoff • = self::C|_#new#tearOff;
+}
+inline class D /* declaredRepresentationType = self::A<Never> */ implements self::B<core::String> {
+ constructor • = self::D|;
+ tearoff • = self::D|_#new#tearOff;
+}
+inline class E /* declaredRepresentationType = self::A<Never> */ {
+ constructor • = self::E|;
+ tearoff • = self::E|_#new#tearOff;
+}
+static inline-class-member method B|<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|::T%> {
+ lowered final self::B<self::B|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method B|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|_#new#tearOff::T%>
+ return self::B|<self::B|_#new#tearOff::T%>(it);
+static inline-class-member method C|<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|::T%> {
+ lowered final self::C<self::C|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method C|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|_#new#tearOff::T%>
+ return self::C|<self::C|_#new#tearOff::T%>(it);
+static inline-class-member method D|(dynamic it) → self::D {
+ lowered final self::D #this = it;
+ return #this;
+}
+static inline-class-member method D|_#new#tearOff(dynamic it) → self::D
+ return self::D|(it);
+static inline-class-member method E|(dynamic it) → self::E {
+ lowered final self::E #this = it;
+ return #this;
+}
+static inline-class-member method E|_#new#tearOff(dynamic it) → self::E
+ return self::E|(it);
diff --git a/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.weak.modular.expect b/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.weak.modular.expect
new file mode 100644
index 0000000..4b905a6
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.weak.modular.expect
@@ -0,0 +1,60 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart:9:16: Error: 'C' is a supertype of itself.
+// extension type C<T>(A<T> it) implements C<T> {}
+// ^
+//
+// pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart:13:16: Error: 'E' is a supertype of itself.
+// extension type E(A<Never> it) implements B<int>, C<String> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T%>
+ : super core::Object::•()
+ ;
+}
+inline class B<T extends core::Object? = dynamic> /* declaredRepresentationType = self::A<T%> */ {
+ constructor • = self::B|;
+ tearoff • = self::B|_#new#tearOff;
+}
+inline class C<T extends core::Object? = dynamic> /* declaredRepresentationType = self::A<T%> */ {
+ constructor • = self::C|;
+ tearoff • = self::C|_#new#tearOff;
+}
+inline class D /* declaredRepresentationType = self::A<Never> */ implements self::B<core::String> {
+ constructor • = self::D|;
+ tearoff • = self::D|_#new#tearOff;
+}
+inline class E /* declaredRepresentationType = self::A<Never> */ {
+ constructor • = self::E|;
+ tearoff • = self::E|_#new#tearOff;
+}
+static inline-class-member method B|<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|::T%> {
+ lowered final self::B<self::B|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method B|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|_#new#tearOff::T%>
+ return self::B|<self::B|_#new#tearOff::T%>(it);
+static inline-class-member method C|<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|::T%> {
+ lowered final self::C<self::C|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method C|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|_#new#tearOff::T%>
+ return self::C|<self::C|_#new#tearOff::T%>(it);
+static inline-class-member method D|(dynamic it) → self::D {
+ lowered final self::D #this = it;
+ return #this;
+}
+static inline-class-member method D|_#new#tearOff(dynamic it) → self::D
+ return self::D|(it);
+static inline-class-member method E|(dynamic it) → self::E {
+ lowered final self::E #this = it;
+ return #this;
+}
+static inline-class-member method E|_#new#tearOff(dynamic it) → self::E
+ return self::E|(it);
diff --git a/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.weak.outline.expect b/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.weak.outline.expect
new file mode 100644
index 0000000..1d75f0b
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.weak.outline.expect
@@ -0,0 +1,51 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart:9:16: Error: 'C' is a supertype of itself.
+// extension type C<T>(A<T> it) implements C<T> {}
+// ^
+//
+// pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart:13:16: Error: 'E' is a supertype of itself.
+// extension type E(A<Never> it) implements B<int>, C<String> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T%>
+ ;
+}
+inline class B<T extends core::Object? = dynamic> /* declaredRepresentationType = self::A<T%> */ {
+ constructor • = self::B|;
+ tearoff • = self::B|_#new#tearOff;
+}
+inline class C<T extends core::Object? = dynamic> /* declaredRepresentationType = self::A<T%> */ {
+ constructor • = self::C|;
+ tearoff • = self::C|_#new#tearOff;
+}
+inline class D /* declaredRepresentationType = self::A<Never> */ implements self::B<core::String> {
+ constructor • = self::D|;
+ tearoff • = self::D|_#new#tearOff;
+}
+inline class E /* declaredRepresentationType = self::A<Never> */ {
+ constructor • = self::E|;
+ tearoff • = self::E|_#new#tearOff;
+}
+static inline-class-member method B|<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|::T%>
+ ;
+static inline-class-member method B|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|_#new#tearOff::T%>
+ return self::B|<self::B|_#new#tearOff::T%>(it);
+static inline-class-member method C|<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|::T%>
+ ;
+static inline-class-member method C|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|_#new#tearOff::T%>
+ return self::C|<self::C|_#new#tearOff::T%>(it);
+static inline-class-member method D|(dynamic it) → self::D
+ ;
+static inline-class-member method D|_#new#tearOff(dynamic it) → self::D
+ return self::D|(it);
+static inline-class-member method E|(dynamic it) → self::E
+ ;
+static inline-class-member method E|_#new#tearOff(dynamic it) → self::E
+ return self::E|(it);
diff --git a/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.weak.transformed.expect b/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.weak.transformed.expect
new file mode 100644
index 0000000..4b905a6
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart.weak.transformed.expect
@@ -0,0 +1,60 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart:9:16: Error: 'C' is a supertype of itself.
+// extension type C<T>(A<T> it) implements C<T> {}
+// ^
+//
+// pkg/front_end/testcases/inline_class/extension_types/supertype_conflict.dart:13:16: Error: 'E' is a supertype of itself.
+// extension type E(A<Never> it) implements B<int>, C<String> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T%>
+ : super core::Object::•()
+ ;
+}
+inline class B<T extends core::Object? = dynamic> /* declaredRepresentationType = self::A<T%> */ {
+ constructor • = self::B|;
+ tearoff • = self::B|_#new#tearOff;
+}
+inline class C<T extends core::Object? = dynamic> /* declaredRepresentationType = self::A<T%> */ {
+ constructor • = self::C|;
+ tearoff • = self::C|_#new#tearOff;
+}
+inline class D /* declaredRepresentationType = self::A<Never> */ implements self::B<core::String> {
+ constructor • = self::D|;
+ tearoff • = self::D|_#new#tearOff;
+}
+inline class E /* declaredRepresentationType = self::A<Never> */ {
+ constructor • = self::E|;
+ tearoff • = self::E|_#new#tearOff;
+}
+static inline-class-member method B|<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|::T%> {
+ lowered final self::B<self::B|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method B|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::B<self::B|_#new#tearOff::T%>
+ return self::B|<self::B|_#new#tearOff::T%>(it);
+static inline-class-member method C|<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|::T%> {
+ lowered final self::C<self::C|::T%> #this = it;
+ return #this;
+}
+static inline-class-member method C|_#new#tearOff<T extends core::Object? = dynamic>(dynamic it) → self::C<self::C|_#new#tearOff::T%>
+ return self::C|<self::C|_#new#tearOff::T%>(it);
+static inline-class-member method D|(dynamic it) → self::D {
+ lowered final self::D #this = it;
+ return #this;
+}
+static inline-class-member method D|_#new#tearOff(dynamic it) → self::D
+ return self::D|(it);
+static inline-class-member method E|(dynamic it) → self::E {
+ lowered final self::E #this = it;
+ return #this;
+}
+static inline-class-member method E|_#new#tearOff(dynamic it) → self::E
+ return self::E|(it);
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index ee5554a..9b2eb84 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -148,6 +148,8 @@
inline_class/extension_types/method_access: FormatterCrash
inline_class/extension_types/procedures: FormatterCrash
inline_class/extension_types/representation: FormatterCrash
+inline_class/extension_types/supertype_conflict: FormatterCrash
+inline_class/extension_types/super_extension_type_conflict: FormatterCrash
late_lowering/later: FormatterCrash
macros/augment_class: FormatterCrash
macros/augment_concrete: FormatterCrash