[CFE] Reproduction & fix of crashes found by weekly bot (#83)

Calling "SpecialCasedBinaryOperator" and "SpecialCasedTernaryOperator"
with wrong number of parameters (especially too few) would not go well.
It's now checked and goes a lot better.

Change-Id: Id9606db869f020bbd7264686adaf9521bd263fb9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/237900
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 53b1b32..1e4d084 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -2488,20 +2488,39 @@
         namedIndex == arguments.named.length,
         "Expected 'namedIndex' to be ${arguments.named.length}, "
         "got ${namedIndex}.");
-    if (isSpecialCasedBinaryOperator) {
-      calleeType = replaceReturnType(
-          calleeType,
-          typeSchemaEnvironment.getTypeOfSpecialCasedBinaryOperator(
-              receiverType!, actualTypes![0],
-              isNonNullableByDefault: isNonNullableByDefault));
-    } else if (isSpecialCasedTernaryOperator) {
-      calleeType = replaceReturnType(
-          calleeType,
-          typeSchemaEnvironment.getTypeOfSpecialCasedTernaryOperator(
-              receiverType!,
-              actualTypes![0],
-              actualTypes[1],
-              libraryBuilder.library));
+
+    if (isSpecialCasedBinaryOperator || isSpecialCasedTernaryOperator) {
+      if (typeChecksNeeded && !identical(calleeType, unknownFunction)) {
+        LocatedMessage? argMessage = helper!.checkArgumentsForType(
+            calleeType, arguments, offset,
+            isExtensionMemberInvocation: isExtensionMemberInvocation);
+        if (argMessage != null) {
+          return new WrapInProblemInferenceResult(
+              const InvalidType(),
+              const InvalidType(),
+              argMessage.messageObject,
+              argMessage.charOffset,
+              argMessage.length,
+              helper!,
+              isInapplicable: true,
+              hoistedArguments: localHoistedExpressions);
+        }
+      }
+      if (isSpecialCasedBinaryOperator) {
+        calleeType = replaceReturnType(
+            calleeType,
+            typeSchemaEnvironment.getTypeOfSpecialCasedBinaryOperator(
+                receiverType!, actualTypes![0],
+                isNonNullableByDefault: isNonNullableByDefault));
+      } else if (isSpecialCasedTernaryOperator) {
+        calleeType = replaceReturnType(
+            calleeType,
+            typeSchemaEnvironment.getTypeOfSpecialCasedTernaryOperator(
+                receiverType!,
+                actualTypes![0],
+                actualTypes[1],
+                libraryBuilder.library));
+      }
     }
 
     // Check for and remove duplicated named arguments.
diff --git a/pkg/front_end/test/fasta/expression_suite.dart b/pkg/front_end/test/fasta/expression_suite.dart
index f7f2528..e8871b6 100644
--- a/pkg/front_end/test/fasta/expression_suite.dart
+++ b/pkg/front_end/test/fasta/expression_suite.dart
@@ -67,6 +67,8 @@
 
 import "package:yaml/yaml.dart" show YamlMap, YamlList, loadYamlNode;
 
+import '../testing_utils.dart' show checkEnvironment;
+
 import '../utils/kernel_chain.dart' show runDiff, openWrite;
 
 class Context extends ChainContext {
@@ -568,6 +570,12 @@
 
 Future<Context> createContext(
     Chain suite, Map<String, String> environment) async {
+  const Set<String> knownEnvironmentKeys = {
+    "updateExpectations",
+    "fuzz",
+  };
+  checkEnvironment(environment, knownEnvironmentKeys);
+
   final Uri base = Uri.parse("org-dartlang-test:///");
 
   /// Unused because we supply entry points to [computeDelta] directly above.
diff --git a/pkg/front_end/testcases/expression/weekly_bot_run_83_crash.expression.yaml b/pkg/front_end/testcases/expression/weekly_bot_run_83_crash.expression.yaml
new file mode 100644
index 0000000..32436f4
--- /dev/null
+++ b/pkg/front_end/testcases/expression/weekly_bot_run_83_crash.expression.yaml
@@ -0,0 +1,9 @@
+# Copyright (c) 2022, 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.
+
+sources: ""
+definitions: []
+position: "dart:core#double"
+expression: |
+  remainder()
diff --git a/pkg/front_end/testcases/expression/weekly_bot_run_83_crash.expression.yaml.expect b/pkg/front_end/testcases/expression/weekly_bot_run_83_crash.expression.yaml.expect
new file mode 100644
index 0000000..562772f
--- /dev/null
+++ b/pkg/front_end/testcases/expression/weekly_bot_run_83_crash.expression.yaml.expect
@@ -0,0 +1,7 @@
+Errors: {
+  org-dartlang-debug:synthetic_debug_expression:1:10: Error: Too few positional arguments: 1 required, 0 given.
+  remainder()
+           ^
+}
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return invalid-expression "org-dartlang-debug:synthetic_debug_expression:1:10: Error: Too few positional arguments: 1 required, 0 given.\nremainder()\n         ^" in this.{dart.core::double::remainder}{<inapplicable>}.(){() → invalid-type};
diff --git a/pkg/front_end/testcases/expression/weekly_bot_run_83_crash_2.expression.yaml b/pkg/front_end/testcases/expression/weekly_bot_run_83_crash_2.expression.yaml
new file mode 100644
index 0000000..06be5ad
--- /dev/null
+++ b/pkg/front_end/testcases/expression/weekly_bot_run_83_crash_2.expression.yaml
@@ -0,0 +1,9 @@
+# Copyright (c) 2022, 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.
+
+sources: ""
+definitions: []
+position: "dart:core#double"
+expression: |
+  clamp()
diff --git a/pkg/front_end/testcases/expression/weekly_bot_run_83_crash_2.expression.yaml.expect b/pkg/front_end/testcases/expression/weekly_bot_run_83_crash_2.expression.yaml.expect
new file mode 100644
index 0000000..79d8f70
--- /dev/null
+++ b/pkg/front_end/testcases/expression/weekly_bot_run_83_crash_2.expression.yaml.expect
@@ -0,0 +1,7 @@
+Errors: {
+  org-dartlang-debug:synthetic_debug_expression:1:6: Error: Too few positional arguments: 2 required, 0 given.
+  clamp()
+       ^
+}
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return invalid-expression "org-dartlang-debug:synthetic_debug_expression:1:6: Error: Too few positional arguments: 2 required, 0 given.\nclamp()\n     ^" in this.{dart.core::num::clamp}{<inapplicable>}.(){() → invalid-type};
diff --git a/pkg/front_end/testcases/expression/weekly_bot_run_83_crash_2_prime.expression.yaml b/pkg/front_end/testcases/expression/weekly_bot_run_83_crash_2_prime.expression.yaml
new file mode 100644
index 0000000..969b867
--- /dev/null
+++ b/pkg/front_end/testcases/expression/weekly_bot_run_83_crash_2_prime.expression.yaml
@@ -0,0 +1,9 @@
+# Copyright (c) 2022, 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.
+
+sources: ""
+definitions: []
+position: "dart:core#double"
+expression: |
+  clamp(42, 42)
diff --git a/pkg/front_end/testcases/expression/weekly_bot_run_83_crash_2_prime.expression.yaml.expect b/pkg/front_end/testcases/expression/weekly_bot_run_83_crash_2_prime.expression.yaml.expect
new file mode 100644
index 0000000..22d3276
--- /dev/null
+++ b/pkg/front_end/testcases/expression/weekly_bot_run_83_crash_2_prime.expression.yaml.expect
@@ -0,0 +1,4 @@
+Errors: {
+}
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return this.{dart.core::num::clamp}(42, 42){(dart.core::num, dart.core::num) → dart.core::num};
diff --git a/pkg/front_end/testcases/expression/weekly_bot_run_83_crash_prime.expression.yaml b/pkg/front_end/testcases/expression/weekly_bot_run_83_crash_prime.expression.yaml
new file mode 100644
index 0000000..ed211a3
--- /dev/null
+++ b/pkg/front_end/testcases/expression/weekly_bot_run_83_crash_prime.expression.yaml
@@ -0,0 +1,9 @@
+# Copyright (c) 2022, 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.
+
+sources: ""
+definitions: []
+position: "dart:core#double"
+expression: |
+  remainder(42)
diff --git a/pkg/front_end/testcases/expression/weekly_bot_run_83_crash_prime.expression.yaml.expect b/pkg/front_end/testcases/expression/weekly_bot_run_83_crash_prime.expression.yaml.expect
new file mode 100644
index 0000000..3d31b64
--- /dev/null
+++ b/pkg/front_end/testcases/expression/weekly_bot_run_83_crash_prime.expression.yaml.expect
@@ -0,0 +1,4 @@
+Errors: {
+}
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return this.{dart.core::double::remainder}(42){(dart.core::num) → dart.core::double};
diff --git a/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart
new file mode 100644
index 0000000..f98757e
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart
@@ -0,0 +1,10 @@
+main2() {
+  double x = 42;
+  x.remainder();
+}
+
+main(List<String> args) {
+  if (args.length == 42) {
+    main2();
+  }
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart.textual_outline.expect b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart.textual_outline.expect
new file mode 100644
index 0000000..db0697d
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart.textual_outline.expect
@@ -0,0 +1,2 @@
+main2() {}
+main(List<String> args) {}
diff --git a/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..8cb08e1
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart.textual_outline_modelled.expect
@@ -0,0 +1,2 @@
+main(List<String> args) {}
+main2() {}
diff --git a/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart.weak.expect b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart.weak.expect
new file mode 100644
index 0000000..8e0ea4f
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart.weak.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart:3:14: Error: Too few positional arguments: 1 required, 0 given.
+//   x.remainder();
+//              ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method main2() → dynamic {
+  core::double x = 42.0;
+  invalid-expression "pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart:3:14: Error: Too few positional arguments: 1 required, 0 given.
+  x.remainder();
+             ^" in x.{core::double::remainder}{<inapplicable>}.(){() → invalid-type};
+}
+static method main(core::List<core::String> args) → dynamic {
+  if(args.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} 42) {
+    self::main2();
+  }
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart.weak.modular.expect b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart.weak.modular.expect
new file mode 100644
index 0000000..8e0ea4f
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart.weak.modular.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart:3:14: Error: Too few positional arguments: 1 required, 0 given.
+//   x.remainder();
+//              ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method main2() → dynamic {
+  core::double x = 42.0;
+  invalid-expression "pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart:3:14: Error: Too few positional arguments: 1 required, 0 given.
+  x.remainder();
+             ^" in x.{core::double::remainder}{<inapplicable>}.(){() → invalid-type};
+}
+static method main(core::List<core::String> args) → dynamic {
+  if(args.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} 42) {
+    self::main2();
+  }
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart.weak.outline.expect b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart.weak.outline.expect
new file mode 100644
index 0000000..250a282
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart.weak.outline.expect
@@ -0,0 +1,8 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method main2() → dynamic
+  ;
+static method main(core::List<core::String> args) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart.weak.transformed.expect b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart.weak.transformed.expect
new file mode 100644
index 0000000..8e0ea4f
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart.weak.transformed.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart:3:14: Error: Too few positional arguments: 1 required, 0 given.
+//   x.remainder();
+//              ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method main2() → dynamic {
+  core::double x = 42.0;
+  invalid-expression "pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure.dart:3:14: Error: Too few positional arguments: 1 required, 0 given.
+  x.remainder();
+             ^" in x.{core::double::remainder}{<inapplicable>}.(){() → invalid-type};
+}
+static method main(core::List<core::String> args) → dynamic {
+  if(args.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} 42) {
+    self::main2();
+  }
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart
new file mode 100644
index 0000000..be427e6
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart
@@ -0,0 +1,10 @@
+main2() {
+  double x = 42;
+  x.clamp();
+}
+
+main(List<String> args) {
+  if (args.length == 42) {
+    main2();
+  }
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart.textual_outline.expect b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart.textual_outline.expect
new file mode 100644
index 0000000..db0697d
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart.textual_outline.expect
@@ -0,0 +1,2 @@
+main2() {}
+main(List<String> args) {}
diff --git a/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..8cb08e1
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart.textual_outline_modelled.expect
@@ -0,0 +1,2 @@
+main(List<String> args) {}
+main2() {}
diff --git a/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart.weak.expect b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart.weak.expect
new file mode 100644
index 0000000..ff2ca09
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart.weak.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart:3:10: Error: Too few positional arguments: 2 required, 0 given.
+//   x.clamp();
+//          ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method main2() → dynamic {
+  core::double x = 42.0;
+  invalid-expression "pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart:3:10: Error: Too few positional arguments: 2 required, 0 given.
+  x.clamp();
+         ^" in x.{core::num::clamp}{<inapplicable>}.(){() → invalid-type};
+}
+static method main(core::List<core::String> args) → dynamic {
+  if(args.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} 42) {
+    self::main2();
+  }
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart.weak.modular.expect b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart.weak.modular.expect
new file mode 100644
index 0000000..ff2ca09
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart.weak.modular.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart:3:10: Error: Too few positional arguments: 2 required, 0 given.
+//   x.clamp();
+//          ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method main2() → dynamic {
+  core::double x = 42.0;
+  invalid-expression "pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart:3:10: Error: Too few positional arguments: 2 required, 0 given.
+  x.clamp();
+         ^" in x.{core::num::clamp}{<inapplicable>}.(){() → invalid-type};
+}
+static method main(core::List<core::String> args) → dynamic {
+  if(args.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} 42) {
+    self::main2();
+  }
+}
diff --git a/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart.weak.outline.expect b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart.weak.outline.expect
new file mode 100644
index 0000000..250a282
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart.weak.outline.expect
@@ -0,0 +1,8 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method main2() → dynamic
+  ;
+static method main(core::List<core::String> args) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart.weak.transformed.expect b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart.weak.transformed.expect
new file mode 100644
index 0000000..ff2ca09
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart.weak.transformed.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart:3:10: Error: Too few positional arguments: 2 required, 0 given.
+//   x.clamp();
+//          ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method main2() → dynamic {
+  core::double x = 42.0;
+  invalid-expression "pkg/front_end/testcases/general/error_recovery/weekly_bot_83_failure_2.dart:3:10: Error: Too few positional arguments: 2 required, 0 given.
+  x.clamp();
+         ^" in x.{core::num::clamp}{<inapplicable>}.(){() → invalid-type};
+}
+static method main(core::List<core::String> args) → dynamic {
+  if(args.{core::List::length}{core::int} =={core::num::==}{(core::Object) → core::bool} 42) {
+    self::main2();
+  }
+}