Version 3.6.0-112.0.dev

Merge b39f386598da16bcc841bd47f45e601c94faf081 into dev
diff --git a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
index 02ec449..75d0d24 100644
--- a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
+++ b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
@@ -2485,6 +2485,8 @@
   status: noFix
   notes: |-
     This would require renaming the method, which is a refactoring.
+LintCode.use_truncating_division:
+  status: hasFix
 LintCode.valid_regexps:
   status: noFix
 LintCode.void_checks:
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 9e25b7c..1184fae 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -383,6 +383,7 @@
 import 'package:linter/src/rules/use_rethrow_when_possible.dart';
 import 'package:linter/src/rules/use_string_in_part_of_directives.dart';
 import 'package:linter/src/rules/use_super_parameters.dart';
+import 'package:linter/src/rules/use_truncating_division.dart';
 
 final _builtInLintMultiProducers = {
   CommentReferences.code: [
@@ -859,6 +860,9 @@
   UseSuperParameters.multipleParams: [
     ConvertToSuperParameters.new,
   ],
+  UseTruncatingDivision.code: [
+    UseEffectiveIntegerDivision.new,
+  ],
 };
 
 final _builtInNonLintMultiProducers = {
diff --git a/pkg/analysis_server/test/services/completion/dart/declaration/wildcard_variables_test.dart b/pkg/analysis_server/test/services/completion/dart/declaration/wildcard_variables_test.dart
index ff191d4..b1b62da 100644
--- a/pkg/analysis_server/test/services/completion/dart/declaration/wildcard_variables_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/declaration/wildcard_variables_test.dart
@@ -8,6 +8,7 @@
 
 void main() {
   defineReflectiveSuite(() {
+    defineReflectiveTests(WildcardCatchClauseTest);
     defineReflectiveTests(WildcardFieldTest);
     defineReflectiveTests(WildcardForLoopTest);
     defineReflectiveTests(WildcardImportPrefixTest);
@@ -17,15 +18,56 @@
   });
 }
 
-/// Fields are binding so not technically wildcards but look just like them.
-@reflectiveTest
-class WildcardFieldTest extends AbstractCompletionDriverTest {
+class AbstractWildCardTest extends AbstractCompletionDriverTest {
   @override
-  Set<String> allowedIdentifiers = {'_'};
+  Set<String> allowedIdentifiers = {'_', '__', '___'};
 
   @override
   bool get includeKeywords => false;
+}
 
+@reflectiveTest
+class WildcardCatchClauseTest extends AbstractWildCardTest {
+  Future<void> test_argumentList() async {
+    await computeSuggestions('''
+void p(Object o) {}
+
+void f() {
+  try {
+  } catch(_, _) {
+    p(^);
+  }
+}
+''');
+    assertResponse(r'''
+suggestions
+''');
+  }
+
+  Future<void> test_argumentList_underscores() async {
+    await computeSuggestions('''
+void p(Object o) {}
+
+void f() {
+  try {
+  } catch(__, ___) {
+    p(^);
+  }
+}
+''');
+    assertResponse(r'''
+suggestions
+  __
+    kind: localVariable
+  ___
+    kind: localVariable
+''');
+  }
+}
+
+/// Fields are binding so not technically wildcards but look just like them.
+@reflectiveTest
+class WildcardFieldTest extends AbstractWildCardTest {
   Future<void> test_argumentList() async {
     await computeSuggestions('''
 void p(Object o) {}
@@ -63,13 +105,7 @@
 }
 
 @reflectiveTest
-class WildcardForLoopTest extends AbstractCompletionDriverTest {
-  @override
-  Set<String> allowedIdentifiers = {'_', '__'};
-
-  @override
-  bool get includeKeywords => false;
-
+class WildcardForLoopTest extends AbstractWildCardTest {
   Future<void> test_forEach_argumentList() async {
     await computeSuggestions('''
 void p(Object o) {}
@@ -136,12 +172,12 @@
 }
 
 @reflectiveTest
-class WildcardImportPrefixTest extends AbstractCompletionDriverTest {
+class WildcardImportPrefixTest extends AbstractWildCardTest {
   @override
-  Set<String> allowedIdentifiers = {'_', '__', 'isBlank'};
-
-  @override
-  bool get includeKeywords => false;
+  Future<void> setUp() async {
+    await super.setUp();
+    allowedIdentifiers.add('isBlank');
+  }
 
   Future<void> test_argumentList() async {
     newFile('$testPackageLibPath/ext.dart', '''
@@ -215,25 +251,19 @@
 }
 
 @reflectiveTest
-class WildcardLocalVariableTest extends AbstractCompletionDriverTest {
-  @override
-  Set<String> allowedIdentifiers = {'_', '__', 'b'};
-
-  @override
-  bool get includeKeywords => false;
-
+class WildcardLocalVariableTest extends AbstractWildCardTest {
   Future<void> test_argumentList() async {
     await computeSuggestions('''
 void p(Object o) {}
 
 void f() {
-  var _, b = 0;
+  var _, b0 = 0;
   p(^);
 }
 ''');
     assertResponse(r'''
 suggestions
-  b
+  b0
     kind: localVariable
 ''');
   }
@@ -270,24 +300,18 @@
 }
 
 @reflectiveTest
-class WildcardParameterTest extends AbstractCompletionDriverTest {
-  @override
-  Set<String> allowedIdentifiers = {'_', '__', 'b'};
-
-  @override
-  bool get includeKeywords => false;
-
+class WildcardParameterTest extends AbstractWildCardTest {
   Future<void> test_argumentList() async {
     await computeSuggestions('''
 void p(Object o) {}
 
-void f(int _, int b) {
+void f(int _, int b0) {
   p(^);
 }
 ''');
     assertResponse('''
 suggestions
-  b
+  b0
     kind: parameter
 ''');
   }
@@ -311,13 +335,7 @@
 /// Top level variables are binding so not technically wildcards but look just
 /// like them.
 @reflectiveTest
-class WildcardTopLevelVariableTest extends AbstractCompletionDriverTest {
-  @override
-  Set<String> allowedIdentifiers = {'_'};
-
-  @override
-  bool get includeKeywords => false;
-
+class WildcardTopLevelVariableTest extends AbstractWildCardTest {
   Future<void> test_argumentList() async {
     await computeSuggestions('''
 int _ = 0;
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index c97b253..738b9cd 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -852,6 +852,8 @@
   /// Checks the passed binary expression for [HintCode.DIVISION_OPTIMIZATION].
   ///
   /// Returns whether a hint code is generated.
+  // TODO(srawlins): Remove this ASAP, as it is being replaced by the
+  // 'use_truncating_division' lint rule, to avoid double reporting.
   bool _checkForDivisionOptimizationHint(BinaryExpression node) {
     if (node.operator.type != TokenType.SLASH) return false;
 
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
index 4a89e18..a875a5a 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
@@ -3828,6 +3828,26 @@
     );
   }
 
+  Future<void> test_method_wildcardParams() async {
+    await _assertWriteOverride(
+      content: '''
+class A {
+  void m(int _, [int _]) { }
+}
+class B extends A {
+}
+''',
+      nameToOverride: 'm',
+      expected: '''
+  @override void m(int _, [int _]) {
+    // TODO: implement m
+  }
+''',
+      displayText: 'm(int _, [int _]) { … }',
+      selection: SourceRange(122, 0),
+    );
+  }
+
   Future<void> test_mixin_method_of_interface() async {
     await _assertWriteOverride(
       content: '''
diff --git a/pkg/analyzer_plugin/test/support/abstract_context.dart b/pkg/analyzer_plugin/test/support/abstract_context.dart
index 3128e9a..9e0838c 100644
--- a/pkg/analyzer_plugin/test/support/abstract_context.dart
+++ b/pkg/analyzer_plugin/test/support/abstract_context.dart
@@ -15,8 +15,10 @@
 import 'package:analyzer/src/test_utilities/mock_sdk.dart';
 import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:analyzer_utilities/test/experiments/experiments.dart';
 import 'package:analyzer_utilities/test/mock_packages/mock_packages.dart';
 import 'package:linter/src/rules.dart';
+import 'package:meta/meta.dart';
 
 /// Finds an [Element] with the given [name].
 Element? findChildElement(Element root, String name, [ElementKind? kind]) {
@@ -45,6 +47,10 @@
 
   List<String> get collectionIncludedPaths => [workspaceRootPath];
 
+  /// Return a list of the experiments that are to be enabled for tests in this
+  /// class, an empty list if there are no experiments that should be enabled.
+  List<String> get experiments => experimentsForTests;
+
   @override
   String get packagesRootPath => '/packages';
 
@@ -112,6 +118,7 @@
     return analysisContext.currentSession;
   }
 
+  @mustCallSuper
   void setUp() {
     createMockSdk(
       resourceProvider: resourceProvider,
@@ -120,8 +127,10 @@
 
     newFolder(testPackageRootPath);
     writeTestPackageConfig();
+    createAnalysisOptionsFile(experiments: experiments);
   }
 
+  @mustCallSuper
   void tearDown() {
     AnalysisEngine.instance.clearCaches();
   }
diff --git a/pkg/linter/example/all.yaml b/pkg/linter/example/all.yaml
index 7b66889..aaa5e4d 100644
--- a/pkg/linter/example/all.yaml
+++ b/pkg/linter/example/all.yaml
@@ -223,5 +223,6 @@
     - use_super_parameters
     - use_test_throws_matchers
     - use_to_and_as_if_applicable
+    - use_truncating_division
     - valid_regexps
     - void_checks
diff --git a/pkg/linter/lib/src/rules.dart b/pkg/linter/lib/src/rules.dart
index 0e73c6f..9a0f5f9 100644
--- a/pkg/linter/lib/src/rules.dart
+++ b/pkg/linter/lib/src/rules.dart
@@ -237,6 +237,7 @@
 import 'rules/use_super_parameters.dart';
 import 'rules/use_test_throws_matchers.dart';
 import 'rules/use_to_and_as_if_applicable.dart';
+import 'rules/use_truncating_division.dart';
 import 'rules/valid_regexps.dart';
 import 'rules/void_checks.dart';
 
@@ -476,6 +477,7 @@
     ..register(UseSuperParameters())
     ..register(UseTestThrowsMatchers())
     ..register(UseToAndAsIfApplicable())
+    ..register(UseTruncatingDivision())
     ..register(ValidRegexps())
     ..register(VoidChecks());
 }
diff --git a/pkg/linter/lib/src/rules/use_truncating_division.dart b/pkg/linter/lib/src/rules/use_truncating_division.dart
new file mode 100644
index 0000000..10bfb7a
--- /dev/null
+++ b/pkg/linter/lib/src/rules/use_truncating_division.dart
@@ -0,0 +1,97 @@
+// Copyright (c) 2024, 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.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+
+import '../analyzer.dart';
+
+const _desc = r'Use truncating division.';
+
+const _details = r'''
+**DO** use truncating division, '~/', instead of regular division ('/') followed
+by 'toInt()'.
+
+Dart features a "truncating division" operator which is the same operation as
+division followed by truncation, but which is more concise and expressive, and
+may be more performant on some platforms, for certain inputs.
+
+**BAD:**
+```dart
+var x = (2 / 3).toInt();
+```
+
+**GOOD:**
+```dart
+var x = 2 ~/ 3;
+```
+
+''';
+
+class UseTruncatingDivision extends LintRule {
+  static const LintCode code = LintCode(
+    'use_truncating_division',
+    'Use truncating division.',
+    correctionMessage:
+        "Try using truncating division, '~/', instead of regular division "
+        "('/') followed by 'toInt()'.",
+  );
+
+  UseTruncatingDivision()
+      : super(
+            name: 'use_truncating_division',
+            description: _desc,
+            details: _details,
+            categories: {LintRuleCategory.languageFeatureUsage});
+
+  @override
+  LintCode get lintCode => code;
+
+  @override
+  void registerNodeProcessors(
+      NodeLintRegistry registry, LinterContext context) {
+    var visitor = _Visitor(this);
+    registry.addBinaryExpression(this, visitor);
+  }
+}
+
+class _Visitor extends SimpleAstVisitor<void> {
+  final LintRule rule;
+
+  _Visitor(this.rule);
+
+  @override
+  void visitBinaryExpression(BinaryExpression node) {
+    if (node.operator.type != TokenType.SLASH) return;
+
+    // Return if the two operands are not each `int`.
+    var leftType = node.leftOperand.staticType;
+    if (leftType == null || !leftType.isDartCoreInt) return;
+
+    var rightType = node.rightOperand.staticType;
+    if (rightType == null || !rightType.isDartCoreInt) return;
+
+    // Return if the '/' operator is not defined in core, or if we don't know
+    // its static type.
+    var methodElement = node.staticElement;
+    if (methodElement == null) return;
+
+    var libraryElement = methodElement.library;
+    if (!libraryElement.isDartCore) return;
+
+    var parent = node.parent;
+    if (parent is! ParenthesizedExpression) return;
+
+    var outermostParentheses = parent.thisOrAncestorMatching(
+            (e) => e.parent is! ParenthesizedExpression)!
+        as ParenthesizedExpression;
+    var grandParent = outermostParentheses.parent;
+    if (grandParent is MethodInvocation &&
+        grandParent.methodName.name == 'toInt' &&
+        grandParent.argumentList.arguments.isEmpty) {
+      rule.reportLint(grandParent);
+    }
+  }
+}
diff --git a/pkg/linter/test/rules/parameter_assignments_test.dart b/pkg/linter/test/rules/parameter_assignments_test.dart
index c6a7a15..94889c8 100644
--- a/pkg/linter/test/rules/parameter_assignments_test.dart
+++ b/pkg/linter/test/rules/parameter_assignments_test.dart
@@ -39,6 +39,17 @@
     ]);
   }
 
+  test_assignment_wildcard() async {
+    await assertDiagnostics(r'''
+void f([int? _]) {
+  _ = 8;
+}
+''', [
+      // No lint.
+      error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 21, 1),
+    ]);
+  }
+
   @FailingTest(reason: 'Closures not implemented')
   test_closure_assignment() async {
     await assertDiagnostics(r'''
diff --git a/pkg/linter/test/rules/use_truncating_division_test.dart b/pkg/linter/test/rules/use_truncating_division_test.dart
new file mode 100644
index 0000000..5d62584
--- /dev/null
+++ b/pkg/linter/test/rules/use_truncating_division_test.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2024, 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.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../rule_test_support.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UseTruncatingDivisionTest);
+  });
+}
+
+@reflectiveTest
+class UseTruncatingDivisionTest extends LintRuleTest {
+  @override
+  String get lintRule => 'use_truncating_division';
+
+  test_double_divide_truncate() async {
+    await assertNoDiagnostics(r'''
+void f(double x, double y) {
+  (x / y).toInt();
+}
+''');
+  }
+
+  test_int_divide_truncate() async {
+    await assertDiagnostics(r'''
+void f(int x, int y) {
+  (x / y).toInt();
+}
+''', [
+      // TODO(srawlins): ASAP, remove this Hint.
+      error(HintCode.DIVISION_OPTIMIZATION, 25, 15),
+      lint(25, 15),
+    ]);
+  }
+
+  test_int_divide_truncate_moreParensAroundDivision() async {
+    await assertDiagnostics(r'''
+void f(int x, int y) {
+  (((x / y))).toInt();
+}
+''', [
+      // TODO(srawlins): ASAP, remove this Hint.
+      error(HintCode.DIVISION_OPTIMIZATION, 25, 19),
+      lint(25, 19),
+    ]);
+  }
+
+  test_int_divide_truncate_moreParensAroundOperands() async {
+    await assertDiagnostics(r'''
+void f(int x, int y) {
+  ((x + 1) / (y - 1)).toInt();
+}
+''', [
+      // TODO(srawlins): ASAP, remove this Hint.
+      error(HintCode.DIVISION_OPTIMIZATION, 25, 27),
+      lint(25, 27),
+    ]);
+  }
+
+  test_intExtensionType_divide_truncate() async {
+    await assertNoDiagnostics(r'''
+void f(ET x, int y) {
+  (x / y).toInt();
+}
+
+extension type ET(int it) {
+  int operator /(int other) => 7;
+}
+''');
+  }
+}
diff --git a/tests/lib/js/static_interop_test/js_function_arity_test.dart b/tests/lib/js/static_interop_test/js_function_arity_test.dart
index caf6243..a7ee811 100644
--- a/tests/lib/js/static_interop_test/js_function_arity_test.dart
+++ b/tests/lib/js/static_interop_test/js_function_arity_test.dart
@@ -208,7 +208,12 @@
   Expect.equals(call(oneOptional.toJS, ['a']), 'a');
   Expect.equals(call(oneOptional.toJS, ['a', 'extra']), 'a');
   Expect.equals(call(oneOptionalThis.toJSCaptureThis, ['a']), 'a');
-  Expect.throws(() => call(oneRequired.toJSCaptureThis, []));
+  if (soundNullSafety) {
+    // `this` can be null or a JSObject depending on strict mode, which in turn
+    // depends on the compiler. To make this consistent, only run when sound
+    // null safety is enabled.
+    Expect.throws(() => call(oneRequired.toJSCaptureThis, []));
+  }
 
   // Function subtyping tests.
   Expect.equals(call((oneOptional as String Function()).toJS, []), 'default');
@@ -389,7 +394,12 @@
   Expect.throws(
       () => call(threeRequiredOneOptional.toJS, ['a', 'b', 'c', true]));
   Expect.throws(() => call(oneRequiredThreeOptional.toJS, [false]));
-  Expect.throws(() => call(oneRequiredThreeOptional.toJSCaptureThis, ['a']));
+  if (soundNullSafety) {
+    // `this` can be null or a JSObject depending on strict mode, which in turn
+    // depends on the compiler. To make this consistent, only run when sound
+    // null safety is enabled.
+    Expect.throws(() => call(oneRequiredThreeOptional.toJSCaptureThis, ['a']));
+  }
 
   // Arity tests.
   Expect.equals(call(fourRequired.toJS, ['a', 'b', 'c', 'd', false]), 'abcd');
diff --git a/tests/web/internal/javascriptobject_extensions_test.dart b/tests/web/internal/javascriptobject_extensions_test.dart
index b6b5ed8..439b24b 100644
--- a/tests/web/internal/javascriptobject_extensions_test.dart
+++ b/tests/web/internal/javascriptobject_extensions_test.dart
@@ -20,6 +20,9 @@
         UnknownJavaScriptObject,
         JSObject;
 
+const isDDC = const bool.fromEnvironment('dart.library._ddc_only');
+const isDart2JS = const bool.fromEnvironment('dart.library._dart2js_only');
+
 @JS()
 external void eval(String code);
 
@@ -35,6 +38,15 @@
   String get name => 'ImplementationClass';
 }
 
+class GenericInterfaceClass<T> {}
+
+@JS('JSClass')
+class GenericJSClass<T> implements GenericInterfaceClass<T> {
+  external GenericJSClass();
+}
+
+class GenericImplementationClass<T> implements GenericJSClass<T> {}
+
 @JS()
 @anonymous
 class AnonymousClass {
@@ -145,20 +157,44 @@
   expect(null is JavaScriptObject, false);
   runtimeIsAndAs<JavaScriptObject>(null, hasUnsoundNullSafety);
 
+  // Most of the following tests don't work in DDC and dart2js. In order to test
+  // the current status on both compilers, we place the current status in the
+  // expectation, and the real expected value in a comment next to it. If at any
+  // point we fix the compilers so we get the real expected value, the
+  // corresponding expectations should be amended.
+
   // Transitive is and as.
   // JS type <: JavaScriptObject <: JSObject
   expect(jsObj is JSObject, true);
   runtimeIsAndAs<JSObject>(jsObj);
   // JavaScriptObject <: JS type <: Dart interface
-  expect(javaScriptObject is InterfaceClass, true);
-  runtimeIsAndAs<InterfaceClass>(javaScriptObject);
+  expect(jsObj is InterfaceClass, isDart2JS /* true */);
+  runtimeIsAndAs<InterfaceClass>(jsObj, isDart2JS /* true */);
+  // Generics should be effectively ignored when a JS interop class implements
+  // a Dart class or vice versa.
+  var jsObjInt = GenericJSClass<int>();
+  expect(jsObjInt is GenericInterfaceClass<int>, isDart2JS /* true */);
+  runtimeIsAndAs<GenericInterfaceClass<int>>(jsObjInt, isDart2JS /* true */);
+  var jsObjString = GenericJSClass<String>();
+  expect(jsObjString is GenericInterfaceClass<int>, isDart2JS /* true */);
+  runtimeIsAndAs<GenericInterfaceClass<int>>(jsObjString, isDart2JS /* true */);
+  expect(javaScriptObject is InterfaceClass, isDart2JS /* true */);
+  runtimeIsAndAs<InterfaceClass>(javaScriptObject, isDart2JS /* true */);
   // Dart implementation <: JS type <: JavaScriptObject
   var impl = ImplementationClass();
-  expect(impl is JavaScriptObject, true);
-  runtimeIsAndAs<JavaScriptObject>(impl);
+  expect(impl is JSClass, true);
+  runtimeIsAndAs<JSClass>(impl);
+  var implInt = GenericImplementationClass<int>();
+  expect(implInt is GenericJSClass<int>, true);
+  runtimeIsAndAs<GenericJSClass<int>>(implInt);
+  var implString = GenericImplementationClass<String>();
+  expect(implString is GenericJSClass<int>, true);
+  runtimeIsAndAs<GenericJSClass<int>>(implString);
+  expect(impl is JavaScriptObject, false /* true */);
+  runtimeIsAndAs<JavaScriptObject>(impl, false /* true */);
   // Dart implementation <: JS type <: JavaScriptObject <: JSObject
-  expect(impl is JSObject, true);
-  runtimeIsAndAs<JSObject>(impl);
+  expect(impl is JSObject, false /* true */);
+  runtimeIsAndAs<JSObject>(impl, false /* true */);
 
   // Test that subtyping with nullability works as expected.
   expect(returnJavaScriptObject is JavaScriptObject? Function(), true);
@@ -167,40 +203,49 @@
 
   // Test that JavaScriptObject can be used in place of package:js types in
   // function types, and vice versa.
-  expect(returnJavaScriptObject is JSClass Function(), true);
-  expect(returnJS is JavaScriptObject Function(), true);
-  expect(returnJavaScriptObject is AnonymousClass Function(), true);
-  expect(returnAnon is JavaScriptObject Function(), true);
+  // TODO(srujzs): We should add tests for subtyping involving generics in each
+  // of these cases. However, it's very unlikely we'll fix the non-generic cases
+  // to begin with, and such tests would be filtered today anyways, so we can
+  // add those tests later if we do fix these.
+  expect(returnJavaScriptObject is JSClass Function(), false /* true */);
+  expect(returnJS is JavaScriptObject Function(), isDDC /* true */);
+  expect(returnJavaScriptObject is AnonymousClass Function(), false /* true */);
+  expect(returnAnon is JavaScriptObject Function(), isDDC /* true */);
 
   // Transitive subtyping.
   // UnknownJavaScriptObject <: JavaScriptObject <: JS type
-  expect(returnUnknownJavaScriptObject is JSClass Function(), true);
+  expect(returnUnknownJavaScriptObject is JSClass Function(), false /* true */);
   // JS type <: JavaScriptObject <: JSObject
-  expect(returnJS is JSObject Function(), true);
+  expect(returnJS is JSObject Function(), isDDC /* true */);
   // JavaScriptObject <: JS type <: Dart interface
-  expect(returnJavaScriptObject is InterfaceClass Function(), true);
+  expect(returnJavaScriptObject is InterfaceClass Function(), false /* true */);
   // Dart implementation <: JS type <: JavaScriptObject
-  expect(returnImpl is JavaScriptObject Function(), true);
+  expect(returnImpl is JavaScriptObject Function(), false /* true */);
   // UnknownJavaScriptObject <: JavaScriptObject <: JS type <: Dart interface
-  expect(returnUnknownJavaScriptObject is InterfaceClass Function(), true);
+  expect(returnUnknownJavaScriptObject is InterfaceClass Function(),
+      false /* true */);
   // Dart implementation <: JS type <: JavaScriptObject <: JSObject
-  expect(returnImpl is JSObject Function(), true);
+  expect(returnImpl is JSObject Function(), false /* true */);
 
   // Run above subtype checks but at runtime.
   expect(confuse(returnJavaScriptObject) is JavaScriptObject? Function(), true);
   expect(confuse(returnNullableJavaScriptObject) is JavaScriptObject Function(),
       hasUnsoundNullSafety);
 
-  expect(confuse(returnJavaScriptObject) is JSClass Function(), true);
+  expect(
+      confuse(returnJavaScriptObject) is JSClass Function(), false /* true */);
   expect(confuse(returnJS) is JavaScriptObject Function(), true);
-  expect(confuse(returnJavaScriptObject) is AnonymousClass Function(), true);
+  expect(confuse(returnJavaScriptObject) is AnonymousClass Function(),
+      false /* true */);
   expect(confuse(returnAnon) is JavaScriptObject Function(), true);
 
-  expect(confuse(returnUnknownJavaScriptObject) is JSClass Function(), true);
+  expect(confuse(returnUnknownJavaScriptObject) is JSClass Function(),
+      isDart2JS /* true */);
   expect(confuse(returnJS) is JSObject Function(), true);
-  expect(confuse(returnJavaScriptObject) is InterfaceClass Function(), true);
-  expect(confuse(returnImpl) is JavaScriptObject Function(), true);
+  expect(confuse(returnJavaScriptObject) is InterfaceClass Function(),
+      false /* true */);
+  expect(confuse(returnImpl) is JavaScriptObject Function(), false /* true */);
   expect(confuse(returnUnknownJavaScriptObject) is InterfaceClass Function(),
-      true);
-  expect(confuse(returnImpl) is JSObject Function(), true);
+      isDart2JS /* true */);
+  expect(confuse(returnImpl) is JSObject Function(), false /* true */);
 }
diff --git a/tools/VERSION b/tools/VERSION
index a2f7ee6..f08e0ba 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 3
 MINOR 6
 PATCH 0
-PRERELEASE 111
+PRERELEASE 112
 PRERELEASE_PATCH 0