[fasta] Allow super-bounded types as bounds of type variables

Change-Id: If1f10d8e5b6d6288696926dc3cab6ad8a3b8d446
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/79701
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Aske Simon Christensen <askesc@google.com>
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
index 151c074..6ad083c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
@@ -338,7 +338,7 @@
     for (TypeParameter parameter in cls.typeParameters) {
       List<TypeArgumentIssue> issues = findTypeArgumentIssues(
           parameter.bound, typeEnvironment,
-          allowSuperBounded: false);
+          allowSuperBounded: true);
       if (issues != null) {
         for (TypeArgumentIssue issue in issues) {
           DartType argument = issue.argument;
@@ -923,9 +923,9 @@
       library.addProblem(
           templateOverrideTypeVariablesMismatch.withArguments(
               "${declaredMember.enclosingClass.name}."
-              "${declaredMember.name.name}",
+                  "${declaredMember.name.name}",
               "${interfaceMember.enclosingClass.name}."
-              "${interfaceMember.name.name}"),
+                  "${interfaceMember.name.name}"),
           declaredMember.fileOffset,
           noLength,
           declaredMember.fileUri,
@@ -960,9 +960,9 @@
             library.addProblem(
                 templateOverrideTypeVariablesMismatch.withArguments(
                     "${declaredMember.enclosingClass.name}."
-                    "${declaredMember.name.name}",
+                        "${declaredMember.name.name}",
                     "${interfaceMember.enclosingClass.name}."
-                    "${interfaceMember.name.name}"),
+                        "${interfaceMember.name.name}"),
                 declaredMember.fileOffset,
                 noLength,
                 declaredMember.fileUri,
@@ -1103,9 +1103,9 @@
       library.addProblem(
           templateOverrideFewerPositionalArguments.withArguments(
               "${declaredMember.enclosingClass.name}."
-              "${declaredMember.name.name}",
+                  "${declaredMember.name.name}",
               "${interfaceMember.enclosingClass.name}."
-              "${interfaceMember.name.name}"),
+                  "${interfaceMember.name.name}"),
           declaredMember.fileOffset,
           noLength,
           declaredMember.fileUri,
@@ -1122,9 +1122,9 @@
       library.addProblem(
           templateOverrideMoreRequiredArguments.withArguments(
               "${declaredMember.enclosingClass.name}."
-              "${declaredMember.name.name}",
+                  "${declaredMember.name.name}",
               "${interfaceMember.enclosingClass.name}."
-              "${interfaceMember.name.name}"),
+                  "${interfaceMember.name.name}"),
           declaredMember.fileOffset,
           noLength,
           declaredMember.fileUri,
@@ -1164,9 +1164,9 @@
       library.addProblem(
           templateOverrideFewerNamedArguments.withArguments(
               "${declaredMember.enclosingClass.name}."
-              "${declaredMember.name.name}",
+                  "${declaredMember.name.name}",
               "${interfaceMember.enclosingClass.name}."
-              "${interfaceMember.name.name}"),
+                  "${interfaceMember.name.name}"),
           declaredMember.fileOffset,
           noLength,
           declaredMember.fileUri,
@@ -1201,10 +1201,10 @@
           library.addProblem(
               templateOverrideMismatchNamedParameter.withArguments(
                   "${declaredMember.enclosingClass.name}."
-                  "${declaredMember.name.name}",
+                      "${declaredMember.name.name}",
                   interfaceNamedParameters.current.name,
                   "${interfaceMember.enclosingClass.name}."
-                  "${interfaceMember.name.name}"),
+                      "${interfaceMember.name.name}"),
               declaredMember.fileOffset,
               noLength,
               declaredMember.fileUri,
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index 706be15..80db2c8 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -1570,7 +1570,7 @@
       for (TypeParameter parameter in typeParameters) {
         checkBoundsInType(
             parameter.bound, typeEnvironment, parameter.fileOffset,
-            allowSuperBounded: false);
+            allowSuperBounded: true);
       }
     }
     if (positionalParameters != null) {
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.strong.expect
index dbf94d5..ce101a2 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.strong.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.strong.expect
@@ -7,12 +7,6 @@
 // class Hest<X extends LinkedListEntry> {}
 //            ^
 //
-// pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart:15:12: Error: Type argument 'LinkedListEntry<dynamic>' doesn't conform to the bound 'LinkedListEntry<E>' of the type variable 'E' on 'LinkedListEntry'.
-//  - 'LinkedListEntry' is from 'dart:collection'.
-// Try changing type arguments so that they conform to the bounds.
-// class Hest<X extends LinkedListEntry> {}
-//            ^
-//
 import self as self;
 import "dart:collection" as col;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.strong.transformed.expect
index dbf94d5..ce101a2 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart.strong.transformed.expect
@@ -7,12 +7,6 @@
 // class Hest<X extends LinkedListEntry> {}
 //            ^
 //
-// pkg/front_end/testcases/instantiate_to_bound/non_simple_from_compiled.dart:15:12: Error: Type argument 'LinkedListEntry<dynamic>' doesn't conform to the bound 'LinkedListEntry<E>' of the type variable 'E' on 'LinkedListEntry'.
-//  - 'LinkedListEntry' is from 'dart:collection'.
-// Try changing type arguments so that they conform to the bounds.
-// class Hest<X extends LinkedListEntry> {}
-//            ^
-//
 import self as self;
 import "dart:collection" as col;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart
new file mode 100644
index 0000000..8ecef66
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2019, 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<X extends Comparable<X>> {}
+
+class B<Y extends A<dynamic>> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.hierarchy.expect b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.hierarchy.expect
new file mode 100644
index 0000000..523e0f4
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.hierarchy.expect
@@ -0,0 +1,53 @@
+Object:
+  superclasses:
+  interfaces:
+  classMembers:
+    Object._haveSameRuntimeType
+    Object.toString
+    Object.runtimeType
+    Object._toString
+    Object._simpleInstanceOf
+    Object._hashCodeRnd
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._objectHashCode
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+A:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+B:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
diff --git a/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.legacy.expect b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.legacy.expect
new file mode 100644
index 0000000..6b8efb5
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.legacy.expect
@@ -0,0 +1,15 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Comparable<self::A::X> = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+class B<Y extends self::A<dynamic> = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::Y>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.legacy.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.legacy.transformed.expect
new file mode 100644
index 0000000..6b8efb5
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.legacy.transformed.expect
@@ -0,0 +1,15 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Comparable<self::A::X> = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+class B<Y extends self::A<dynamic> = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::Y>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.outline.expect b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.outline.expect
new file mode 100644
index 0000000..9a334ff
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.outline.expect
@@ -0,0 +1,14 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Comparable<self::A::X> = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    ;
+}
+class B<Y extends self::A<dynamic> = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::Y>
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.strong.expect
new file mode 100644
index 0000000..88cbec9
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.strong.expect
@@ -0,0 +1,15 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Comparable<self::A::X> = core::Comparable<dynamic>> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+class B<Y extends self::A<dynamic> = self::A<dynamic>> extends core::Object {
+  synthetic constructor •() → self::B<self::B::Y>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.strong.transformed.expect
new file mode 100644
index 0000000..88cbec9
--- /dev/null
+++ b/pkg/front_end/testcases/instantiate_to_bound/super_bounded_in_bound.dart.strong.transformed.expect
@@ -0,0 +1,15 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::Comparable<self::A::X> = core::Comparable<dynamic>> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+}
+class B<Y extends self::A<dynamic> = self::A<dynamic>> extends core::Object {
+  synthetic constructor •() → self::B<self::B::Y>
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 25584dc..0347606 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -660,6 +660,7 @@
 instantiate_to_bound/non_simple_variables_from_same: TextSerializationFailure # Was: Pass
 instantiate_to_bound/omitted_bound: TextSerializationFailure # Was: Pass
 instantiate_to_bound/raw_in_bound: TextSerializationFailure # Was: Pass
+instantiate_to_bound/super_bounded_in_bound: TextSerializationFailure
 instantiate_to_bound/super_bounded_type: TextSerializationFailure # Was: Pass
 instantiate_to_bound/supertypes: TextSerializationFailure # Was: Pass
 instantiate_to_bound/typedef_instantiated_in_outline: TextSerializationFailure # Was: Pass
@@ -922,8 +923,8 @@
 regress/issue_36400: TextSerializationFailure
 regress/issue_36647: TextSerializationFailure
 regress/issue_36647_2: TextSerializationFailure
-regress/issue_36793: TextSerializationFailure
 regress/issue_36669: TextSerializationFailure
+regress/issue_36793: TextSerializationFailure
 reject_generic_function_types_in_bounds: TextSerializationFailure # Was: RuntimeError # Expected
 return_with_unknown_type_in_context: TextSerializationFailure # Was: Pass
 runtime_checks/call_kinds: TextSerializationFailure # Was: Pass