Fix TypeSwitch for Java 23

Fixes: b/382880986
Change-Id: I5f839ad4f05f761dce620f4de1bee1a2d7d15352
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index aab3dff..0cf6dec 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -868,7 +868,6 @@
       createMethod(switchBootstrapType, switchBootstrapMethodProto, createString("typeSwitch"));
   public final DexMethod enumSwitchMethod =
       createMethod(switchBootstrapType, switchBootstrapMethodProto, createString("enumSwitch"));
-  public final DexProto typeSwitchProto = createProto(intType, objectType, intType);
   public final DexMethod enumDescMethod =
       createMethod(
           enumDescType, createProto(enumDescType, classDescType, stringType), ofMethodName);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/typeswitch/TypeSwitchDesugaringHelper.java b/src/main/java/com/android/tools/r8/ir/desugar/typeswitch/TypeSwitchDesugaringHelper.java
index 8d20c19..128bda9 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/typeswitch/TypeSwitchDesugaringHelper.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/typeswitch/TypeSwitchDesugaringHelper.java
@@ -29,9 +29,15 @@
         "Unexpected ConstantDynamic in TypeSwitch: " + msg, context.getOrigin());
   }
 
+  private static boolean isTypeSwitchProto(DexProto proto) {
+    return proto.getReturnType().isIntType()
+        && proto.getArity() == 2
+        && proto.getParameter(1).isIntType();
+  }
+
   public static boolean isTypeSwitchCallSite(DexCallSite callSite, DexItemFactory factory) {
     return callSite.methodName.isIdenticalTo(factory.typeSwitchMethod.getName())
-        && callSite.methodProto.isIdenticalTo(factory.typeSwitchProto)
+        && isTypeSwitchProto(callSite.methodProto)
         && methodHandleIsInvokeStaticTo(callSite.bootstrapMethod, factory.typeSwitchMethod);
   }
 
diff --git a/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/EnumLessCasesAtRuntimeSwitchTest.java b/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/EnumLessCasesAtRuntimeSwitchTest.java
index e367e8a..3625fe1 100644
--- a/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/EnumLessCasesAtRuntimeSwitchTest.java
+++ b/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/EnumLessCasesAtRuntimeSwitchTest.java
@@ -3,15 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.java23.switchpatternmatching;
 
-import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
 import static com.android.tools.r8.desugar.switchpatternmatching.SwitchTestHelper.hasJdk21EnumSwitch;
 import static com.android.tools.r8.desugar.switchpatternmatching.SwitchTestHelper.hasJdk21TypeSwitch;
-import static org.hamcrest.CoreMatchers.containsString;
-import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
-import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.JdkClassFileProvider;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestBuilder;
@@ -19,11 +15,9 @@
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.TestRuntime.CfVm;
 import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import org.junit.Assume;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -84,38 +78,20 @@
 
   @Test
   public void testD8() throws Exception {
-    if (parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.O)
-        && parameters.getApiLevel().isLessThan(AndroidApiLevel.BAKLAVA)) {
-      assertThrows(
-          CompilationFailedException.class,
-          () ->
-              testForD8(parameters.getBackend())
-                  .apply(this::addModifiedProgramClasses)
-                  .setMinApi(parameters)
-                  .compileWithExpectedDiagnostics(
-                      diagnostics -> {
-                        diagnostics.assertOnlyErrors();
-                        diagnostics.assertErrorsMatch(
-                            diagnosticMessage(
-                                containsString("DexValueConstDynamic should be desugared")));
-                      }));
-    } else {
-      testForD8(parameters.getBackend())
-          .apply(this::addModifiedProgramClasses)
-          .setMinApi(parameters)
-          .run(parameters.getRuntime(), Main.class)
-          .assertFailure();
-    }
+    testForD8(parameters.getBackend())
+        .apply(this::addModifiedProgramClasses)
+        .setMinApi(parameters)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutput(EXPECTED_OUTPUT);
   }
 
   @Test
-  @Ignore("TODO(b/382880986) enable test when fixed.")
   public void testR8() throws Exception {
     parameters.assumeR8TestParameters();
     Assume.assumeTrue(
         parameters.isDexRuntime()
             || (parameters.isCfRuntime()
-                && parameters.getCfRuntime().isNewerThanOrEqual(CfVm.JDK21)));
+                && parameters.getCfRuntime().isNewerThanOrEqual(CfVm.JDK23)));
     testForR8(parameters.getBackend())
         .apply(this::addModifiedProgramClasses)
         .applyIf(
diff --git a/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/EnumMoreCasesAtRuntimeSwitchTest.java b/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/EnumMoreCasesAtRuntimeSwitchTest.java
index 8b3f44d..51d0386 100644
--- a/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/EnumMoreCasesAtRuntimeSwitchTest.java
+++ b/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/EnumMoreCasesAtRuntimeSwitchTest.java
@@ -3,16 +3,13 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.java23.switchpatternmatching;
 
-import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
+import static com.android.tools.r8.desugar.switchpatternmatching.SwitchTestHelper.desugarMatchException;
 import static com.android.tools.r8.desugar.switchpatternmatching.SwitchTestHelper.hasJdk21EnumSwitch;
 import static com.android.tools.r8.desugar.switchpatternmatching.SwitchTestHelper.hasJdk21TypeSwitch;
 import static com.android.tools.r8.desugar.switchpatternmatching.SwitchTestHelper.matchException;
-import static org.hamcrest.CoreMatchers.containsString;
-import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
-import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.JdkClassFileProvider;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestBuilder;
@@ -20,11 +17,9 @@
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.TestRuntime.CfVm;
 import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import org.junit.Assume;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -133,38 +128,21 @@
 
   @Test
   public void testD8() throws Exception {
-    if (parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.O)
-        && parameters.getApiLevel().isLessThan(AndroidApiLevel.BAKLAVA)) {
-      assertThrows(
-          CompilationFailedException.class,
-          () ->
-              testForD8(parameters.getBackend())
-                  .apply(this::addModifiedProgramClasses)
-                  .setMinApi(parameters)
-                  .compileWithExpectedDiagnostics(
-                      diagnostics -> {
-                        diagnostics.assertOnlyErrors();
-                        diagnostics.assertErrorsMatch(
-                            diagnosticMessage(
-                                containsString("DexValueConstDynamic should be desugared")));
-                      }));
-    } else {
-      testForD8(parameters.getBackend())
-          .apply(this::addModifiedProgramClasses)
-          .setMinApi(parameters)
-          .run(parameters.getRuntime(), Main.class)
-          .assertFailure();
-    }
+    testForD8(parameters.getBackend())
+        .apply(this::addModifiedProgramClasses)
+        .setMinApi(parameters)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutput(
+            String.format(EXPECTED_OUTPUT, desugarMatchException(), desugarMatchException()));
   }
 
   @Test
-  @Ignore("TODO(b/382880986) enable test when fixed.")
   public void testR8() throws Exception {
     parameters.assumeR8TestParameters();
     Assume.assumeTrue(
         parameters.isDexRuntime()
             || (parameters.isCfRuntime()
-                && parameters.getCfRuntime().isNewerThanOrEqual(CfVm.JDK21)));
+                && parameters.getCfRuntime().isNewerThanOrEqual(CfVm.JDK23)));
     testForR8(parameters.getBackend())
         .apply(this::addModifiedProgramClasses)
         .applyIf(
diff --git a/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/EnumSwitchTest.java b/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/EnumSwitchTest.java
index ddf16a8..585c7c2 100644
--- a/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/EnumSwitchTest.java
+++ b/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/EnumSwitchTest.java
@@ -3,15 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.java23.switchpatternmatching;
 
-import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
+import static com.android.tools.r8.desugar.switchpatternmatching.SwitchTestHelper.desugarMatchException;
 import static com.android.tools.r8.desugar.switchpatternmatching.SwitchTestHelper.hasJdk21TypeSwitch;
 import static com.android.tools.r8.desugar.switchpatternmatching.SwitchTestHelper.matchException;
-import static org.hamcrest.CoreMatchers.containsString;
-import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
-import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.JdkClassFileProvider;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestBuilder;
@@ -19,11 +16,9 @@
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.TestRuntime.CfVm;
 import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import org.junit.Assume;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -65,6 +60,7 @@
 
   private <T extends TestBuilder<?, T>> void addModifiedProgramClasses(
       TestBuilder<?, T> testBuilder) throws Exception {
+    String d = "com/android/tools/r8/java23/switchpatternmatching/EnumSwitchTest$D";
     testBuilder
         .addStrippedOuter(getClass())
         .addProgramClasses(FakeI.class, E.class, C.class)
@@ -76,57 +72,32 @@
         .addProgramClassFileData(
             transformer(Main.class)
                 .transformTypeInsnInMethod(
-                    "getD",
-                    (opcode, type, visitor) ->
-                        visitor.visitTypeInsn(opcode, "switchpatternmatching/EnumSwitchTest$D"))
+                    "getD", (opcode, type, visitor) -> visitor.visitTypeInsn(opcode, d))
                 .transformMethodInsnInMethod(
                     "getD",
                     (opcode, owner, name, descriptor, isInterface, visitor) -> {
                       assert name.equals("<init>");
-                      visitor.visitMethodInsn(
-                          opcode,
-                          "switchpatternmatching/EnumSwitchTest$D",
-                          name,
-                          descriptor,
-                          isInterface);
+                      visitor.visitMethodInsn(opcode, d, name, descriptor, isInterface);
                     })
                 .transform());
   }
 
   @Test
   public void testD8() throws Exception {
-    if (parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.O)
-        && parameters.getApiLevel().isLessThan(AndroidApiLevel.BAKLAVA)) {
-      assertThrows(
-          CompilationFailedException.class,
-          () ->
-              testForD8(parameters.getBackend())
-                  .apply(this::addModifiedProgramClasses)
-                  .setMinApi(parameters)
-                  .compileWithExpectedDiagnostics(
-                      diagnostics -> {
-                        diagnostics.assertOnlyErrors();
-                        diagnostics.assertErrorsMatch(
-                            diagnosticMessage(
-                                containsString("DexValueConstDynamic should be desugared")));
-                      }));
-    } else {
-      testForD8(parameters.getBackend())
-          .apply(this::addModifiedProgramClasses)
-          .setMinApi(parameters)
-          .run(parameters.getRuntime(), Main.class)
-          .assertFailure();
-    }
+    testForD8(parameters.getBackend())
+        .apply(this::addModifiedProgramClasses)
+        .setMinApi(parameters)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutput(String.format(EXPECTED_OUTPUT, desugarMatchException()));
   }
 
   @Test
-  @Ignore("TODO(b/382880986) enable test when fixed.")
   public void testR8() throws Exception {
     parameters.assumeR8TestParameters();
     Assume.assumeTrue(
         parameters.isDexRuntime()
             || (parameters.isCfRuntime()
-                && parameters.getCfRuntime().isNewerThanOrEqual(CfVm.JDK21)));
+                && parameters.getCfRuntime().isNewerThanOrEqual(CfVm.JDK23)));
     testForR8(parameters.getBackend())
         .apply(this::addModifiedProgramClasses)
         .applyIf(
diff --git a/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/StringSwitchRegress382880986Test.java b/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/StringSwitchRegress382880986Test.java
index d6c5acb..0f5077e 100644
--- a/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/StringSwitchRegress382880986Test.java
+++ b/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/StringSwitchRegress382880986Test.java
@@ -4,7 +4,6 @@
 package com.android.tools.r8.java23.switchpatternmatching;
 
 import static com.android.tools.r8.desugar.switchpatternmatching.SwitchTestHelper.hasJdk21TypeSwitch;
-import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.JdkClassFileProvider;
@@ -13,11 +12,9 @@
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.TestRuntime.CfVm;
 import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import org.junit.Assume;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -62,17 +59,10 @@
         .addInnerClassesAndStrippedOuter(getClass())
         .setMinApi(parameters)
         .run(parameters.getRuntime(), TestClass.class, "hello", "goodbye", "")
-        // TODO(b/382880986): This should not fail.
-        .applyIf(
-            parameters.getApiLevel().isLessThan(AndroidApiLevel.O),
-            r ->
-                r.assertFailureWithErrorThatMatches(
-                    containsString("Instruction is unrepresentable in DEX")),
-            r -> r.assertFailureWithErrorThatThrows(NoClassDefFoundError.class));
+        .assertSuccessWithOutput(EXPECTED_OUTPUT);
   }
 
   @Test
-  @Ignore("TODO(b/382880986) enable test when fixed.")
   public void testR8() throws Exception {
     Assume.assumeTrue(
         parameters.isDexRuntime()
diff --git a/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/StringSwitchTest.java b/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/StringSwitchTest.java
index 38f7007..4782bf3 100644
--- a/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/StringSwitchTest.java
+++ b/src/test/java23/com/android/tools/r8/java23/switchpatternmatching/StringSwitchTest.java
@@ -3,9 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.java23.switchpatternmatching;
 
-import static com.android.tools.r8.ToolHelper.DexVm.Version.V6_0_1;
 import static com.android.tools.r8.desugar.switchpatternmatching.SwitchTestHelper.hasJdk21TypeSwitch;
-import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
@@ -15,11 +13,9 @@
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.TestRuntime.CfVm;
 import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import org.junit.Assume;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -67,37 +63,16 @@
         .addInnerClassesAndStrippedOuter(getClass())
         .setMinApi(parameters)
         .run(parameters.getRuntime(), Main.class)
-        // TODO(b/382880986): This should not fail.
-        .applyIf(
-            parameters.isDexRuntime() && parameters.asDexRuntime().getVersion().isEqualTo(V6_0_1),
-            r ->
-                r.assertFailureWithErrorThatMatches(
-                    containsString(
-                        "Attempt to invoke virtual method 'boolean"
-                            + " java.lang.String.equalsIgnoreCase(java.lang.String)' on a null"
-                            + " object reference")),
-            parameters.getApiLevel().isLessThan(AndroidApiLevel.O),
-            r ->
-                r.assertFailureWithErrorThatMatches(
-                    containsString("Instruction is unrepresentable in DEX")),
-            parameters.isCfRuntime()
-                && (parameters.asCfRuntime().isNewerThanOrEqual(CfVm.JDK17)
-                    && parameters.asCfRuntime().isOlderThan(CfVm.JDK23)),
-            r -> r.assertFailureWithErrorThatThrows(BootstrapMethodError.class),
-            !parameters.isCfRuntime()
-                || parameters.isCfRuntime() && parameters.asCfRuntime().isOlderThan(CfVm.JDK17),
-            r -> r.assertFailureWithErrorThatThrows(NoClassDefFoundError.class),
-            r -> r.assertSuccessWithOutput(EXPECTED_OUTPUT));
+        .assertSuccessWithOutput(EXPECTED_OUTPUT);
   }
 
   @Test
-  @Ignore("TODO(b/382880986) enable test when fixed.")
   public void testR8() throws Exception {
     parameters.assumeR8TestParameters();
     Assume.assumeTrue(
         parameters.isDexRuntime()
             || (parameters.isCfRuntime()
-                && parameters.getCfRuntime().isNewerThanOrEqual(CfVm.JDK21)));
+                && parameters.getCfRuntime().isNewerThanOrEqual(CfVm.JDK23)));
     testForR8(parameters.getBackend())
         .addInnerClassesAndStrippedOuter(getClass())
         .applyIf(