[cfe] Check superbounded extension types

Closes #53139

Change-Id: I2f13d77454e2a7bac70d19afa1fb321815aac3bc
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/318641
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/lib/src/fasta/builder/extension_type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/extension_type_declaration_builder.dart
index 24ad3085..6fca442 100644
--- a/pkg/front_end/lib/src/fasta/builder/extension_type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/extension_type_declaration_builder.dart
@@ -5,6 +5,7 @@
 import 'package:kernel/ast.dart';
 
 import '../scope.dart';
+import '../source/source_library_builder.dart';
 import 'builder.dart';
 import 'builder_mixins.dart';
 import 'declaration_builder.dart';
@@ -76,7 +77,13 @@
       Uri fileUri,
       int charOffset,
       {required bool hasExplicitTypeArguments}) {
-    return new ExtensionType(extensionTypeDeclaration, nullability, arguments);
+    ExtensionType type =
+        new ExtensionType(extensionTypeDeclaration, nullability, arguments);
+    if (typeVariablesCount != 0 && library is SourceLibraryBuilder) {
+      library.registerBoundsCheck(type, fileUri, charOffset, typeUse,
+          inferred: !hasExplicitTypeArguments);
+    }
+    return type;
   }
 
   @override
diff --git a/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart b/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart
new file mode 100644
index 0000000..75a84f6
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart
@@ -0,0 +1,9 @@
+// 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 V<T extends V<T>>(T id) {}
+
+test(V v) {
+  List<V> l = [v];
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.strong.expect b/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.strong.expect
new file mode 100644
index 0000000..20f288d
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.strong.expect
@@ -0,0 +1,36 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:7:6: Error: Inferred type argument 'V<dynamic>' doesn't conform to the bound 'V<T>' of the type variable 'T' on 'ExtensionType(V<V<dynamic>>)'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// test(V v) {
+//      ^
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:5:18: Context: This is the type variable whose bound isn't conformed to.
+// extension type V<T extends V<T>>(T id) {}
+//                  ^
+//
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:8:8: Error: Inferred type argument 'V<dynamic>' doesn't conform to the bound 'V<T>' of the type variable 'T' on 'ExtensionType(V<V<dynamic>>)'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   List<V> l = [v];
+//        ^
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:5:18: Context: This is the type variable whose bound isn't conformed to.
+// extension type V<T extends V<T>>(T id) {}
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+inline class V<T extends self::V<T> = self::V<dynamic>> /* declaredRepresentationType = T */ {
+  constructor • = self::V|;
+  tearoff • = self::V|_#new#tearOff;
+}
+static inline-class-member method V|<T extends self::V<self::V|::T> = dynamic>(dynamic id) → self::V<self::V|::T> {
+  lowered final self::V<self::V|::T> #this = id;
+  return #this;
+}
+static inline-class-member method V|_#new#tearOff<T extends self::V<self::V|_#new#tearOff::T> = dynamic>(dynamic id) → self::V<self::V|_#new#tearOff::T>
+  return self::V|<self::V|_#new#tearOff::T>(id);
+static method test(self::V<self::V<dynamic>> v) → dynamic {
+  core::List<self::V<self::V<dynamic>>> l = <self::V<self::V<dynamic>>>[v];
+}
diff --git a/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.strong.transformed.expect b/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.strong.transformed.expect
new file mode 100644
index 0000000..1dd36f8
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.strong.transformed.expect
@@ -0,0 +1,36 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:7:6: Error: Inferred type argument 'V<dynamic>' doesn't conform to the bound 'V<T>' of the type variable 'T' on 'ExtensionType(V<V<dynamic>>)'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// test(V v) {
+//      ^
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:5:18: Context: This is the type variable whose bound isn't conformed to.
+// extension type V<T extends V<T>>(T id) {}
+//                  ^
+//
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:8:8: Error: Inferred type argument 'V<dynamic>' doesn't conform to the bound 'V<T>' of the type variable 'T' on 'ExtensionType(V<V<dynamic>>)'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   List<V> l = [v];
+//        ^
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:5:18: Context: This is the type variable whose bound isn't conformed to.
+// extension type V<T extends V<T>>(T id) {}
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+inline class V<T extends self::V<T> = self::V<dynamic>> /* declaredRepresentationType = T */ {
+  constructor • = self::V|;
+  tearoff • = self::V|_#new#tearOff;
+}
+static inline-class-member method V|<T extends self::V<self::V|::T> = dynamic>(dynamic id) → self::V<self::V|::T> {
+  lowered final self::V<self::V|::T> #this = id;
+  return #this;
+}
+static inline-class-member method V|_#new#tearOff<T extends self::V<self::V|_#new#tearOff::T> = dynamic>(dynamic id) → self::V<self::V|_#new#tearOff::T>
+  return self::V|<self::V|_#new#tearOff::T>(id);
+static method test(self::V<self::V<dynamic>> v) → dynamic {
+  core::List<self::V<self::V<dynamic>>> l = core::_GrowableList::_literal1<self::V<self::V<dynamic>>>(v);
+}
diff --git a/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.textual_outline.expect b/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.textual_outline.expect
new file mode 100644
index 0000000..11f4b74
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.textual_outline.expect
@@ -0,0 +1,2 @@
+extension type V<T extends V<T>>(T id) {}
+test(V v) {}
diff --git a/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.weak.expect b/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.weak.expect
new file mode 100644
index 0000000..20f288d
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.weak.expect
@@ -0,0 +1,36 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:7:6: Error: Inferred type argument 'V<dynamic>' doesn't conform to the bound 'V<T>' of the type variable 'T' on 'ExtensionType(V<V<dynamic>>)'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// test(V v) {
+//      ^
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:5:18: Context: This is the type variable whose bound isn't conformed to.
+// extension type V<T extends V<T>>(T id) {}
+//                  ^
+//
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:8:8: Error: Inferred type argument 'V<dynamic>' doesn't conform to the bound 'V<T>' of the type variable 'T' on 'ExtensionType(V<V<dynamic>>)'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   List<V> l = [v];
+//        ^
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:5:18: Context: This is the type variable whose bound isn't conformed to.
+// extension type V<T extends V<T>>(T id) {}
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+inline class V<T extends self::V<T> = self::V<dynamic>> /* declaredRepresentationType = T */ {
+  constructor • = self::V|;
+  tearoff • = self::V|_#new#tearOff;
+}
+static inline-class-member method V|<T extends self::V<self::V|::T> = dynamic>(dynamic id) → self::V<self::V|::T> {
+  lowered final self::V<self::V|::T> #this = id;
+  return #this;
+}
+static inline-class-member method V|_#new#tearOff<T extends self::V<self::V|_#new#tearOff::T> = dynamic>(dynamic id) → self::V<self::V|_#new#tearOff::T>
+  return self::V|<self::V|_#new#tearOff::T>(id);
+static method test(self::V<self::V<dynamic>> v) → dynamic {
+  core::List<self::V<self::V<dynamic>>> l = <self::V<self::V<dynamic>>>[v];
+}
diff --git a/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.weak.modular.expect b/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.weak.modular.expect
new file mode 100644
index 0000000..20f288d
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.weak.modular.expect
@@ -0,0 +1,36 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:7:6: Error: Inferred type argument 'V<dynamic>' doesn't conform to the bound 'V<T>' of the type variable 'T' on 'ExtensionType(V<V<dynamic>>)'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// test(V v) {
+//      ^
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:5:18: Context: This is the type variable whose bound isn't conformed to.
+// extension type V<T extends V<T>>(T id) {}
+//                  ^
+//
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:8:8: Error: Inferred type argument 'V<dynamic>' doesn't conform to the bound 'V<T>' of the type variable 'T' on 'ExtensionType(V<V<dynamic>>)'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   List<V> l = [v];
+//        ^
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:5:18: Context: This is the type variable whose bound isn't conformed to.
+// extension type V<T extends V<T>>(T id) {}
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+inline class V<T extends self::V<T> = self::V<dynamic>> /* declaredRepresentationType = T */ {
+  constructor • = self::V|;
+  tearoff • = self::V|_#new#tearOff;
+}
+static inline-class-member method V|<T extends self::V<self::V|::T> = dynamic>(dynamic id) → self::V<self::V|::T> {
+  lowered final self::V<self::V|::T> #this = id;
+  return #this;
+}
+static inline-class-member method V|_#new#tearOff<T extends self::V<self::V|_#new#tearOff::T> = dynamic>(dynamic id) → self::V<self::V|_#new#tearOff::T>
+  return self::V|<self::V|_#new#tearOff::T>(id);
+static method test(self::V<self::V<dynamic>> v) → dynamic {
+  core::List<self::V<self::V<dynamic>>> l = <self::V<self::V<dynamic>>>[v];
+}
diff --git a/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.weak.outline.expect b/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.weak.outline.expect
new file mode 100644
index 0000000..d200706
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.weak.outline.expect
@@ -0,0 +1,24 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:7:6: Error: Inferred type argument 'V<dynamic>' doesn't conform to the bound 'V<T>' of the type variable 'T' on 'ExtensionType(V<V<dynamic>>)'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// test(V v) {
+//      ^
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:5:18: Context: This is the type variable whose bound isn't conformed to.
+// extension type V<T extends V<T>>(T id) {}
+//                  ^
+//
+import self as self;
+
+inline class V<T extends self::V<T> = self::V<dynamic>> /* declaredRepresentationType = T */ {
+  constructor • = self::V|;
+  tearoff • = self::V|_#new#tearOff;
+}
+static inline-class-member method V|<T extends self::V<self::V|::T> = dynamic>(dynamic id) → self::V<self::V|::T>
+  ;
+static inline-class-member method V|_#new#tearOff<T extends self::V<self::V|_#new#tearOff::T> = dynamic>(dynamic id) → self::V<self::V|_#new#tearOff::T>
+  return self::V|<self::V|_#new#tearOff::T>(id);
+static method test(self::V<self::V<dynamic>> v) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.weak.transformed.expect b/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.weak.transformed.expect
new file mode 100644
index 0000000..1dd36f8
--- /dev/null
+++ b/pkg/front_end/testcases/inline_class/extension_types/issue53123.dart.weak.transformed.expect
@@ -0,0 +1,36 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:7:6: Error: Inferred type argument 'V<dynamic>' doesn't conform to the bound 'V<T>' of the type variable 'T' on 'ExtensionType(V<V<dynamic>>)'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// test(V v) {
+//      ^
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:5:18: Context: This is the type variable whose bound isn't conformed to.
+// extension type V<T extends V<T>>(T id) {}
+//                  ^
+//
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:8:8: Error: Inferred type argument 'V<dynamic>' doesn't conform to the bound 'V<T>' of the type variable 'T' on 'ExtensionType(V<V<dynamic>>)'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   List<V> l = [v];
+//        ^
+// pkg/front_end/testcases/inline_class/extension_types/issue53123.dart:5:18: Context: This is the type variable whose bound isn't conformed to.
+// extension type V<T extends V<T>>(T id) {}
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+inline class V<T extends self::V<T> = self::V<dynamic>> /* declaredRepresentationType = T */ {
+  constructor • = self::V|;
+  tearoff • = self::V|_#new#tearOff;
+}
+static inline-class-member method V|<T extends self::V<self::V|::T> = dynamic>(dynamic id) → self::V<self::V|::T> {
+  lowered final self::V<self::V|::T> #this = id;
+  return #this;
+}
+static inline-class-member method V|_#new#tearOff<T extends self::V<self::V|_#new#tearOff::T> = dynamic>(dynamic id) → self::V<self::V|_#new#tearOff::T>
+  return self::V|<self::V|_#new#tearOff::T>(id);
+static method test(self::V<self::V<dynamic>> v) → dynamic {
+  core::List<self::V<self::V<dynamic>>> l = core::_GrowableList::_literal1<self::V<self::V<dynamic>>>(v);
+}
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index 696d87e..06ab9a6 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -148,6 +148,7 @@
 inline_class/extension_types/issue52284: FormatterCrash
 inline_class/extension_types/issue52525: FormatterCrash
 inline_class/extension_types/issue52667: FormatterCrash
+inline_class/extension_types/issue53123: FormatterCrash
 inline_class/extension_types/member_not_found: FormatterCrash
 inline_class/extension_types/method_access: FormatterCrash
 inline_class/extension_types/non_covariant_type_parameter: FormatterCrash
diff --git a/pkg/kernel/lib/src/bounds_checks.dart b/pkg/kernel/lib/src/bounds_checks.dart
index eec83b3..0d508c4 100644
--- a/pkg/kernel/lib/src/bounds_checks.dart
+++ b/pkg/kernel/lib/src/bounds_checks.dart
@@ -342,6 +342,10 @@
   } else if (type is TypedefType) {
     variables = type.typedefNode.typeParameters;
     arguments = type.typeArguments;
+  } else if (type is ExtensionType) {
+    variables = type.extensionTypeDeclaration.typeParameters;
+    arguments = type.typeArguments;
+    allowSuperBounded = false;
   } else if (type is FunctionType) {
     List<TypeArgumentIssue> result = <TypeArgumentIssue>[];
 
@@ -372,6 +376,12 @@
     variables = typeEnvironment.coreTypes.futureClass.typeParameters;
     arguments = <DartType>[type.typeArgument];
   } else {
+    assert(type is DynamicType ||
+        type is VoidType ||
+        type is IntersectionType ||
+        type is TypeParameterType ||
+        type is NeverType ||
+        type is NullType);
     return const <TypeArgumentIssue>[];
   }