[fasta] Fix an issue with override inference and type parameters

The CL fixes how override-based inference works in the cases when the
type of a parameter in the overriding method is omitted, and the type
of this parameter in the overridden method contains a type parameter
of the class.  Basically, the type should be substituted in this case.

Change-Id: I36d6c614d47e5cd68dc14eae1a2bbe4cd19d842b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/104784
Reviewed-by: Aske Simon Christensen <askesc@google.com>
diff --git a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
index 040d468..597ce11 100644
--- a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
@@ -737,7 +737,13 @@
         VariableDeclaration bParameter = bNamed[bCount];
         copyParameterCovariance(a.parent, aParameter, bParameter);
         DartType aType = aParameter.type;
+        if (aSubstitution != null) {
+          aType = aSubstitution.substituteType(aType);
+        }
         DartType bType = bParameter.type;
+        if (bSubstitution != null) {
+          bType = bSubstitution.substituteType(bType);
+        }
         if (substitution != null) {
           bType = substitution.substituteType(bType);
         }
diff --git a/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart b/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart
new file mode 100644
index 0000000..f905aee
--- /dev/null
+++ b/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart
@@ -0,0 +1,13 @@
+// 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.
+
+abstract class A<X> {
+  void foo({Iterable<X> x});
+}
+
+class B<Y> implements A<Y> {
+  void foo({x}) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart.hierarchy.expect b/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart.hierarchy.expect
new file mode 100644
index 0000000..c985c1b
--- /dev/null
+++ b/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart.hierarchy.expect
@@ -0,0 +1,69 @@
+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
+    A.foo
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+B:
+  Longest path to Object: 2
+  superclasses:
+    Object
+  interfaces: A<Y>
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    B.foo
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+  interfaceMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    B.foo
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  interfaceSetters:
diff --git a/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart.legacy.expect b/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart.legacy.expect
new file mode 100644
index 0000000..a036a98
--- /dev/null
+++ b/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart.legacy.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+  abstract method foo({generic-covariant-impl core::Iterable<self::A::X> x = null}) → void;
+}
+class B<Y extends core::Object = dynamic> extends core::Object implements self::A<self::B::Y> {
+  synthetic constructor •() → self::B<self::B::Y>
+    : super core::Object::•()
+    ;
+  method foo({generic-covariant-impl core::Iterable<self::B::Y> x = null}) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart.legacy.transformed.expect b/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart.legacy.transformed.expect
new file mode 100644
index 0000000..a036a98
--- /dev/null
+++ b/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart.legacy.transformed.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+  abstract method foo({generic-covariant-impl core::Iterable<self::A::X> x = null}) → void;
+}
+class B<Y extends core::Object = dynamic> extends core::Object implements self::A<self::B::Y> {
+  synthetic constructor •() → self::B<self::B::Y>
+    : super core::Object::•()
+    ;
+  method foo({generic-covariant-impl core::Iterable<self::B::Y> x = null}) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart.outline.expect b/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart.outline.expect
new file mode 100644
index 0000000..986c56b
--- /dev/null
+++ b/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart.outline.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    ;
+  abstract method foo({generic-covariant-impl core::Iterable<self::A::X> x}) → void;
+}
+class B<Y extends core::Object = dynamic> extends core::Object implements self::A<self::B::Y> {
+  synthetic constructor •() → self::B<self::B::Y>
+    ;
+  method foo({generic-covariant-impl core::Iterable<self::B::Y> x}) → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart.strong.expect b/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart.strong.expect
new file mode 100644
index 0000000..a036a98
--- /dev/null
+++ b/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart.strong.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+  abstract method foo({generic-covariant-impl core::Iterable<self::A::X> x = null}) → void;
+}
+class B<Y extends core::Object = dynamic> extends core::Object implements self::A<self::B::Y> {
+  synthetic constructor •() → self::B<self::B::Y>
+    : super core::Object::•()
+    ;
+  method foo({generic-covariant-impl core::Iterable<self::B::Y> x = null}) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart.strong.transformed.expect
new file mode 100644
index 0000000..a036a98
--- /dev/null
+++ b/pkg/front_end/testcases/inference/override_inference_with_type_parameters.dart.strong.transformed.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class A<X extends core::Object = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X>
+    : super core::Object::•()
+    ;
+  abstract method foo({generic-covariant-impl core::Iterable<self::A::X> x = null}) → void;
+}
+class B<Y extends core::Object = dynamic> extends core::Object implements self::A<self::B::Y> {
+  synthetic constructor •() → self::B<self::B::Y>
+    : super core::Object::•()
+    ;
+  method foo({generic-covariant-impl core::Iterable<self::B::Y> x = null}) → void {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 43c0eb4..ef897a2 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -475,6 +475,7 @@
 inference/overloaded_int_operators: TextSerializationFailure # Was: Pass
 inference/override_equals: TextSerializationFailure # Was: RuntimeError
 inference/override_inference_depends_on_field_inference: TextSerializationFailure
+inference/override_inference_with_type_parameters: TextSerializationFailure
 inference/parameter_defaults_downwards: TextSerializationFailure # Was: Pass
 inference/parameter_defaults_upwards: TextSerializationFailure # Was: Pass
 inference/promote_bounds: TextSerializationFailure # Was: Pass