[fasta] Fix erroneous dependence of inference on named parameters order

Change-Id: I7013b4c4340a7d6fd543a21f14ac318ff0ecb4d7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/106080
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 597ce11..d61cbca 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
@@ -748,8 +748,13 @@
           bType = substitution.substituteType(bType);
         }
         if (aType != bType) {
-          FormalParameterBuilder<KernelTypeBuilder> parameter =
-              a.formals[aPositional.length + aCount];
+          FormalParameterBuilder<KernelTypeBuilder> parameter;
+          for (int i = aPositional.length; i < a.formals.length; ++i) {
+            if (a.formals[i].name == name) {
+              parameter = a.formals[i];
+              break;
+            }
+          }
           if (a.parent == cls && parameter.type == null) {
             result = inferParameterType(
                 cls, a, parameter, bType, hadTypesInferred, hierarchy);
diff --git a/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart b/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart
new file mode 100644
index 0000000..d5210c1
--- /dev/null
+++ b/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart
@@ -0,0 +1,35 @@
+// 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.
+
+// The test checks that override-based inference for named parameters isn't
+// affected by the name-based ordering of the parameters.
+
+class A {
+  foo({bool c = true, bool a}) {}
+}
+
+class B extends A {
+  foo({c = true, bool a}) {}
+}
+
+class C extends B {
+  foo({bool c = true, bool a}) {}
+}
+
+// A1, B1, and C1 are similar to A, B, and C, only they have the names of the
+// named parameters swapped, to test that the alternative ordering works.
+
+class A1 {
+  foo({bool a = true, bool c}) {}
+}
+
+class B1 extends A1 {
+  foo({a = true, bool c}) {}
+}
+
+class C1 extends B1 {
+  foo({bool a = true, bool c}) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart.hierarchy.expect b/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart.hierarchy.expect
new file mode 100644
index 0000000..9fb9b41
--- /dev/null
+++ b/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart.hierarchy.expect
@@ -0,0 +1,133 @@
+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:
+  superclasses:
+    Object
+      -> A
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    B.foo
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+C:
+  superclasses:
+    Object
+      -> A
+        -> B
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    C.foo
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+A1:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    A1.foo
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+B1:
+  superclasses:
+    Object
+      -> A1
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    B1.foo
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+C1:
+  superclasses:
+    Object
+      -> A1
+        -> B1
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    C1.foo
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
diff --git a/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart.legacy.expect b/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart.legacy.expect
new file mode 100644
index 0000000..498e65c
--- /dev/null
+++ b/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart.legacy.expect
@@ -0,0 +1,41 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method foo({core::bool c = true, core::bool a = null}) → dynamic {}
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+  method foo({core::bool c = true, core::bool a = null}) → dynamic {}
+}
+class C extends self::B {
+  synthetic constructor •() → self::C
+    : super self::B::•()
+    ;
+  method foo({core::bool c = true, core::bool a = null}) → dynamic {}
+}
+class A1 extends core::Object {
+  synthetic constructor •() → self::A1
+    : super core::Object::•()
+    ;
+  method foo({core::bool a = true, core::bool c = null}) → dynamic {}
+}
+class B1 extends self::A1 {
+  synthetic constructor •() → self::B1
+    : super self::A1::•()
+    ;
+  method foo({core::bool a = true, core::bool c = null}) → dynamic {}
+}
+class C1 extends self::B1 {
+  synthetic constructor •() → self::C1
+    : super self::B1::•()
+    ;
+  method foo({core::bool a = true, core::bool c = null}) → dynamic {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart.legacy.transformed.expect b/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart.legacy.transformed.expect
new file mode 100644
index 0000000..498e65c
--- /dev/null
+++ b/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart.legacy.transformed.expect
@@ -0,0 +1,41 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method foo({core::bool c = true, core::bool a = null}) → dynamic {}
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+  method foo({core::bool c = true, core::bool a = null}) → dynamic {}
+}
+class C extends self::B {
+  synthetic constructor •() → self::C
+    : super self::B::•()
+    ;
+  method foo({core::bool c = true, core::bool a = null}) → dynamic {}
+}
+class A1 extends core::Object {
+  synthetic constructor •() → self::A1
+    : super core::Object::•()
+    ;
+  method foo({core::bool a = true, core::bool c = null}) → dynamic {}
+}
+class B1 extends self::A1 {
+  synthetic constructor •() → self::B1
+    : super self::A1::•()
+    ;
+  method foo({core::bool a = true, core::bool c = null}) → dynamic {}
+}
+class C1 extends self::B1 {
+  synthetic constructor •() → self::C1
+    : super self::B1::•()
+    ;
+  method foo({core::bool a = true, core::bool c = null}) → dynamic {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart.outline.expect b/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart.outline.expect
new file mode 100644
index 0000000..7a732b2
--- /dev/null
+++ b/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart.outline.expect
@@ -0,0 +1,42 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    ;
+  method foo({core::bool c, core::bool a}) → dynamic
+    ;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    ;
+  method foo({core::bool c, core::bool a}) → dynamic
+    ;
+}
+class C extends self::B {
+  synthetic constructor •() → self::C
+    ;
+  method foo({core::bool c, core::bool a}) → dynamic
+    ;
+}
+class A1 extends core::Object {
+  synthetic constructor •() → self::A1
+    ;
+  method foo({core::bool a, core::bool c}) → dynamic
+    ;
+}
+class B1 extends self::A1 {
+  synthetic constructor •() → self::B1
+    ;
+  method foo({core::bool a, core::bool c}) → dynamic
+    ;
+}
+class C1 extends self::B1 {
+  synthetic constructor •() → self::C1
+    ;
+  method foo({core::bool a, core::bool c}) → dynamic
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart.strong.expect b/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart.strong.expect
new file mode 100644
index 0000000..498e65c
--- /dev/null
+++ b/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart.strong.expect
@@ -0,0 +1,41 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method foo({core::bool c = true, core::bool a = null}) → dynamic {}
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+  method foo({core::bool c = true, core::bool a = null}) → dynamic {}
+}
+class C extends self::B {
+  synthetic constructor •() → self::C
+    : super self::B::•()
+    ;
+  method foo({core::bool c = true, core::bool a = null}) → dynamic {}
+}
+class A1 extends core::Object {
+  synthetic constructor •() → self::A1
+    : super core::Object::•()
+    ;
+  method foo({core::bool a = true, core::bool c = null}) → dynamic {}
+}
+class B1 extends self::A1 {
+  synthetic constructor •() → self::B1
+    : super self::A1::•()
+    ;
+  method foo({core::bool a = true, core::bool c = null}) → dynamic {}
+}
+class C1 extends self::B1 {
+  synthetic constructor •() → self::C1
+    : super self::B1::•()
+    ;
+  method foo({core::bool a = true, core::bool c = null}) → dynamic {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart.strong.transformed.expect b/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart.strong.transformed.expect
new file mode 100644
index 0000000..498e65c
--- /dev/null
+++ b/pkg/front_end/testcases/override_inference_named_parameters_ordering.dart.strong.transformed.expect
@@ -0,0 +1,41 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  method foo({core::bool c = true, core::bool a = null}) → dynamic {}
+}
+class B extends self::A {
+  synthetic constructor •() → self::B
+    : super self::A::•()
+    ;
+  method foo({core::bool c = true, core::bool a = null}) → dynamic {}
+}
+class C extends self::B {
+  synthetic constructor •() → self::C
+    : super self::B::•()
+    ;
+  method foo({core::bool c = true, core::bool a = null}) → dynamic {}
+}
+class A1 extends core::Object {
+  synthetic constructor •() → self::A1
+    : super core::Object::•()
+    ;
+  method foo({core::bool a = true, core::bool c = null}) → dynamic {}
+}
+class B1 extends self::A1 {
+  synthetic constructor •() → self::B1
+    : super self::A1::•()
+    ;
+  method foo({core::bool a = true, core::bool c = null}) → dynamic {}
+}
+class C1 extends self::B1 {
+  synthetic constructor •() → self::C1
+    : super self::B1::•()
+    ;
+  method foo({core::bool a = true, core::bool c = null}) → dynamic {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index ef897a2..32535ad 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -757,6 +757,7 @@
 override_check_two_substitutions: TextSerializationFailure # Was: Pass
 override_check_with_covariant_modifier: TypeCheckError # Issue #31620
 override_inference_for_setters: TextSerializationFailure
+override_inference_named_parameters_ordering: TextSerializationFailure
 part_as_entry_point: TextSerializationFailure # Was: Pass
 part_as_entry_point_lib: TextSerializationFailure # Was: Pass
 part_not_part_of: TextSerializationFailure