[cfe] Adjust the number of optional positional parameters in DOWN

This CL brings the CFE into agreement with the spec and the Analyzer
for function types with optional positional parameters by adjusting
the number of such parameters.

Close https://github.com/dart-lang/sdk/issues/49044

Change-Id: I0d15bb5b4b10c5ca18b78c985e3424899155a3c6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/245367
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/testcases/nnbd/issue49044.dart b/pkg/front_end/testcases/nnbd/issue49044.dart
new file mode 100644
index 0000000..48ca34c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue49044.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2021, 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.
+
+X bar<X>(Function(X) f) => throw 0;
+
+foo(Function(Function(int, int, [int])) f, Function(Function(int, [int])) g) {
+  var x = [f, g];
+  var h = x.first;
+  var u = bar(h);
+  Function(int, [int, int]) v = u;
+  return v;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue49044.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue49044.dart.strong.expect
new file mode 100644
index 0000000..f8ab478ab
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue49044.dart.strong.expect
@@ -0,0 +1,14 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method bar<X extends core::Object? = dynamic>((self::bar::X%) → dynamic f) → self::bar::X%
+  return throw 0;
+static method foo(((core::int, core::int, [core::int]) → dynamic) → dynamic f, ((core::int, [core::int]) → dynamic) → dynamic g) → dynamic {
+  core::List<((core::int, [core::int, core::int]) → dynamic) → dynamic> x = <((core::int, [core::int, core::int]) → dynamic) → dynamic>[f, g];
+  ((core::int, [core::int, core::int]) → dynamic) → dynamic h = x.{core::Iterable::first}{((core::int, [core::int, core::int]) → dynamic) → dynamic};
+  (core::int, [core::int, core::int]) → dynamic u = self::bar<(core::int, [core::int, core::int]) → dynamic>(h);
+  (core::int, [core::int, core::int]) → dynamic v = u;
+  return v;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue49044.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue49044.dart.strong.transformed.expect
new file mode 100644
index 0000000..af6207a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue49044.dart.strong.transformed.expect
@@ -0,0 +1,14 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method bar<X extends core::Object? = dynamic>((self::bar::X%) → dynamic f) → self::bar::X%
+  return throw 0;
+static method foo(((core::int, core::int, [core::int]) → dynamic) → dynamic f, ((core::int, [core::int]) → dynamic) → dynamic g) → dynamic {
+  core::List<((core::int, [core::int, core::int]) → dynamic) → dynamic> x = core::_GrowableList::_literal2<((core::int, [core::int, core::int]) → dynamic) → dynamic>(f, g);
+  ((core::int, [core::int, core::int]) → dynamic) → dynamic h = x.{core::Iterable::first}{((core::int, [core::int, core::int]) → dynamic) → dynamic};
+  (core::int, [core::int, core::int]) → dynamic u = self::bar<(core::int, [core::int, core::int]) → dynamic>(h);
+  (core::int, [core::int, core::int]) → dynamic v = u;
+  return v;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue49044.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue49044.dart.textual_outline.expect
new file mode 100644
index 0000000..9824f66
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue49044.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+X bar<X>(Function(X) f) => throw 0;
+foo(Function(Function(int, int, [int])) f, Function(Function(int, [int])) g) {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue49044.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue49044.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..9824f66
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue49044.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+X bar<X>(Function(X) f) => throw 0;
+foo(Function(Function(int, int, [int])) f, Function(Function(int, [int])) g) {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue49044.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue49044.dart.weak.expect
new file mode 100644
index 0000000..f8ab478ab
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue49044.dart.weak.expect
@@ -0,0 +1,14 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method bar<X extends core::Object? = dynamic>((self::bar::X%) → dynamic f) → self::bar::X%
+  return throw 0;
+static method foo(((core::int, core::int, [core::int]) → dynamic) → dynamic f, ((core::int, [core::int]) → dynamic) → dynamic g) → dynamic {
+  core::List<((core::int, [core::int, core::int]) → dynamic) → dynamic> x = <((core::int, [core::int, core::int]) → dynamic) → dynamic>[f, g];
+  ((core::int, [core::int, core::int]) → dynamic) → dynamic h = x.{core::Iterable::first}{((core::int, [core::int, core::int]) → dynamic) → dynamic};
+  (core::int, [core::int, core::int]) → dynamic u = self::bar<(core::int, [core::int, core::int]) → dynamic>(h);
+  (core::int, [core::int, core::int]) → dynamic v = u;
+  return v;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue49044.dart.weak.modular.expect b/pkg/front_end/testcases/nnbd/issue49044.dart.weak.modular.expect
new file mode 100644
index 0000000..f8ab478ab
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue49044.dart.weak.modular.expect
@@ -0,0 +1,14 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method bar<X extends core::Object? = dynamic>((self::bar::X%) → dynamic f) → self::bar::X%
+  return throw 0;
+static method foo(((core::int, core::int, [core::int]) → dynamic) → dynamic f, ((core::int, [core::int]) → dynamic) → dynamic g) → dynamic {
+  core::List<((core::int, [core::int, core::int]) → dynamic) → dynamic> x = <((core::int, [core::int, core::int]) → dynamic) → dynamic>[f, g];
+  ((core::int, [core::int, core::int]) → dynamic) → dynamic h = x.{core::Iterable::first}{((core::int, [core::int, core::int]) → dynamic) → dynamic};
+  (core::int, [core::int, core::int]) → dynamic u = self::bar<(core::int, [core::int, core::int]) → dynamic>(h);
+  (core::int, [core::int, core::int]) → dynamic v = u;
+  return v;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue49044.dart.weak.outline.expect b/pkg/front_end/testcases/nnbd/issue49044.dart.weak.outline.expect
new file mode 100644
index 0000000..562f3d9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue49044.dart.weak.outline.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method bar<X extends core::Object? = dynamic>((self::bar::X%) → dynamic f) → self::bar::X%
+  ;
+static method foo(((core::int, core::int, [core::int]) → dynamic) → dynamic f, ((core::int, [core::int]) → dynamic) → dynamic g) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue49044.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue49044.dart.weak.transformed.expect
new file mode 100644
index 0000000..af6207a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue49044.dart.weak.transformed.expect
@@ -0,0 +1,14 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method bar<X extends core::Object? = dynamic>((self::bar::X%) → dynamic f) → self::bar::X%
+  return throw 0;
+static method foo(((core::int, core::int, [core::int]) → dynamic) → dynamic f, ((core::int, [core::int]) → dynamic) → dynamic g) → dynamic {
+  core::List<((core::int, [core::int, core::int]) → dynamic) → dynamic> x = core::_GrowableList::_literal2<((core::int, [core::int, core::int]) → dynamic) → dynamic>(f, g);
+  ((core::int, [core::int, core::int]) → dynamic) → dynamic h = x.{core::Iterable::first}{((core::int, [core::int, core::int]) → dynamic) → dynamic};
+  (core::int, [core::int, core::int]) → dynamic u = self::bar<(core::int, [core::int, core::int]) → dynamic>(h);
+  (core::int, [core::int, core::int]) → dynamic v = u;
+  return v;
+}
+static method main() → dynamic {}
diff --git a/pkg/kernel/lib/src/standard_bounds.dart b/pkg/kernel/lib/src/standard_bounds.dart
index 452fcc2..4263359 100644
--- a/pkg/kernel/lib/src/standard_bounds.dart
+++ b/pkg/kernel/lib/src/standard_bounds.dart
@@ -1042,7 +1042,8 @@
         intersectNullabilities(f.declaredNullability, g.declaredNullability),
         namedParameters: namedParameters,
         typeParameters: typeParameters,
-        requiredParameterCount: minPos);
+        requiredParameterCount:
+            math.min(f.requiredParameterCount, g.requiredParameterCount));
   }
 
   /// Computes the nullability-aware lower bound of two function types.