Merge commit '3f85de8f78cc6d952ede610b841141b6f806008b' into dev-release
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
index 37e327f..edc591e 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
@@ -12,6 +12,8 @@
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.structural.Equatable;
 import com.android.tools.r8.utils.structural.Ordered;
+import it.unimi.dsi.fastutil.ints.IntArraySet;
+import it.unimi.dsi.fastutil.ints.IntSet;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -23,64 +25,67 @@
   private KindGenerator generator = new KindGenerator();
 
   // Global synthetics.
-  public final SyntheticKind RECORD_TAG = generator.forGlobalClass();
-  public final SyntheticKind API_MODEL_STUB = generator.forGlobalClass();
+  public final SyntheticKind RECORD_TAG = generator.forGlobalClass(1);
+  public final SyntheticKind API_MODEL_STUB = generator.forGlobalClass(33);
 
   // Classpath only synthetics in the global type namespace.
-  public final SyntheticKind RETARGET_STUB = generator.forGlobalClasspathClass();
-  public final SyntheticKind EMULATED_INTERFACE_MARKER_CLASS = generator.forGlobalClasspathClass();
+  public final SyntheticKind RETARGET_STUB = generator.forGlobalClasspathClass(36);
+  public final SyntheticKind EMULATED_INTERFACE_MARKER_CLASS =
+      generator.forGlobalClasspathClass(29);
 
   // Fixed suffix synthetics. Each has a hygienic prefix type.
   public final SyntheticKind ENUM_UNBOXING_LOCAL_UTILITY_CLASS =
-      generator.forFixedClass("$EnumUnboxingLocalUtility");
+      generator.forFixedClass(24, "$EnumUnboxingLocalUtility");
   public final SyntheticKind ENUM_UNBOXING_SHARED_UTILITY_CLASS =
-      generator.forFixedClass("$EnumUnboxingSharedUtility");
-  public final SyntheticKind COMPANION_CLASS = generator.forFixedClass("$-CC");
+      generator.forFixedClass(25, "$EnumUnboxingSharedUtility");
+  public final SyntheticKind COMPANION_CLASS = generator.forFixedClass(2, "$-CC");
   public final SyntheticKind EMULATED_INTERFACE_CLASS =
-      generator.forFixedClass(InterfaceDesugaringForTesting.EMULATED_INTERFACE_CLASS_SUFFIX);
-  public final SyntheticKind RETARGET_CLASS = generator.forFixedClass("RetargetClass");
-  public final SyntheticKind RETARGET_INTERFACE = generator.forFixedClass("RetargetInterface");
-  public final SyntheticKind WRAPPER = generator.forFixedClass("$Wrapper");
-  public final SyntheticKind VIVIFIED_WRAPPER = generator.forFixedClass("$VivifiedWrapper");
-  public final SyntheticKind INIT_TYPE_ARGUMENT = generator.forFixedClass("-IA");
+      generator.forFixedClass(3, InterfaceDesugaringForTesting.EMULATED_INTERFACE_CLASS_SUFFIX);
+  public final SyntheticKind RETARGET_CLASS = generator.forFixedClass(20, "RetargetClass");
+  public final SyntheticKind RETARGET_INTERFACE = generator.forFixedClass(21, "RetargetInterface");
+  public final SyntheticKind WRAPPER = generator.forFixedClass(22, "$Wrapper");
+  public final SyntheticKind VIVIFIED_WRAPPER = generator.forFixedClass(23, "$VivifiedWrapper");
+  public final SyntheticKind INIT_TYPE_ARGUMENT = generator.forFixedClass(5, "-IA");
   public final SyntheticKind HORIZONTAL_INIT_TYPE_ARGUMENT_1 =
-      generator.forFixedClass(SYNTHETIC_CLASS_SEPARATOR + "IA$1");
+      generator.forFixedClass(6, SYNTHETIC_CLASS_SEPARATOR + "IA$1");
   public final SyntheticKind HORIZONTAL_INIT_TYPE_ARGUMENT_2 =
-      generator.forFixedClass(SYNTHETIC_CLASS_SEPARATOR + "IA$2");
+      generator.forFixedClass(7, SYNTHETIC_CLASS_SEPARATOR + "IA$2");
   public final SyntheticKind HORIZONTAL_INIT_TYPE_ARGUMENT_3 =
-      generator.forFixedClass(SYNTHETIC_CLASS_SEPARATOR + "IA$3");
-  public final SyntheticKind ENUM_CONVERSION = generator.forFixedClass("$EnumConversion");
+      generator.forFixedClass(8, SYNTHETIC_CLASS_SEPARATOR + "IA$3");
+  public final SyntheticKind ENUM_CONVERSION = generator.forFixedClass(31, "$EnumConversion");
 
   // Locally generated synthetic classes.
-  public final SyntheticKind LAMBDA = generator.forInstanceClass("Lambda");
+  public final SyntheticKind LAMBDA = generator.forInstanceClass(4, "Lambda");
 
   // TODO(b/214901256): Sharing of synthetic classes may lead to duplicate method errors.
   public final SyntheticKind NON_FIXED_INIT_TYPE_ARGUMENT =
-      generator.forNonSharableInstanceClass("$IA");
-  public final SyntheticKind CONST_DYNAMIC = generator.forInstanceClass("$Condy");
+      generator.forNonSharableInstanceClass(35, "$IA");
+  public final SyntheticKind CONST_DYNAMIC = generator.forInstanceClass(30, "$Condy");
 
   // Method synthetics.
   public final SyntheticKind ENUM_UNBOXING_CHECK_NOT_ZERO_METHOD =
-      generator.forSingleMethod("CheckNotZero");
-  public final SyntheticKind RECORD_HELPER = generator.forSingleMethod("Record");
-  public final SyntheticKind BACKPORT = generator.forSingleMethod("Backport");
+      generator.forSingleMethod(27, "CheckNotZero");
+  public final SyntheticKind RECORD_HELPER = generator.forSingleMethod(9, "Record");
+  public final SyntheticKind BACKPORT = generator.forSingleMethod(10, "Backport");
   public final SyntheticKind BACKPORT_WITH_FORWARDING =
-      generator.forSingleMethod("BackportWithForwarding");
+      generator.forSingleMethod(34, "BackportWithForwarding");
   public final SyntheticKind STATIC_INTERFACE_CALL =
-      generator.forSingleMethod("StaticInterfaceCall");
-  public final SyntheticKind TO_STRING_IF_NOT_NULL = generator.forSingleMethod("ToStringIfNotNull");
-  public final SyntheticKind THROW_CCE_IF_NOT_NULL = generator.forSingleMethod("ThrowCCEIfNotNull");
-  public final SyntheticKind THROW_IAE = generator.forSingleMethod("ThrowIAE");
-  public final SyntheticKind THROW_ICCE = generator.forSingleMethod("ThrowICCE");
-  public final SyntheticKind THROW_NSME = generator.forSingleMethod("ThrowNSME");
-  public final SyntheticKind TWR_CLOSE_RESOURCE = generator.forSingleMethod("TwrCloseResource");
-  public final SyntheticKind SERVICE_LOADER = generator.forSingleMethod("ServiceLoad");
-  public final SyntheticKind OUTLINE = generator.forSingleMethod("Outline");
-  public final SyntheticKind API_CONVERSION = generator.forSingleMethod("APIConversion");
+      generator.forSingleMethod(11, "StaticInterfaceCall");
+  public final SyntheticKind TO_STRING_IF_NOT_NULL =
+      generator.forSingleMethod(12, "ToStringIfNotNull");
+  public final SyntheticKind THROW_CCE_IF_NOT_NULL =
+      generator.forSingleMethod(13, "ThrowCCEIfNotNull");
+  public final SyntheticKind THROW_IAE = generator.forSingleMethod(14, "ThrowIAE");
+  public final SyntheticKind THROW_ICCE = generator.forSingleMethod(15, "ThrowICCE");
+  public final SyntheticKind THROW_NSME = generator.forSingleMethod(16, "ThrowNSME");
+  public final SyntheticKind TWR_CLOSE_RESOURCE = generator.forSingleMethod(17, "TwrCloseResource");
+  public final SyntheticKind SERVICE_LOADER = generator.forSingleMethod(18, "ServiceLoad");
+  public final SyntheticKind OUTLINE = generator.forSingleMethod(19, "Outline");
+  public final SyntheticKind API_CONVERSION = generator.forSingleMethod(26, "APIConversion");
   public final SyntheticKind API_CONVERSION_PARAMETERS =
-      generator.forSingleMethod("APIConversionParameters");
-  public final SyntheticKind ARRAY_CONVERSION = generator.forSingleMethod("$ArrayConversion");
-  public final SyntheticKind API_MODEL_OUTLINE = generator.forSingleMethod("ApiModelOutline");
+      generator.forSingleMethod(28, "APIConversionParameters");
+  public final SyntheticKind ARRAY_CONVERSION = generator.forSingleMethod(37, "$ArrayConversion");
+  public final SyntheticKind API_MODEL_OUTLINE = generator.forSingleMethod(32, "ApiModelOutline");
 
   private final List<SyntheticKind> ALL_KINDS = generator.getAllKinds();
 
@@ -89,48 +94,49 @@
   }
 
   public SyntheticKind fromId(int id) {
-    if (0 < id && id <= ALL_KINDS.size()) {
-      return ALL_KINDS.get(id - 1);
+    for (SyntheticKind kind : ALL_KINDS) {
+      if (kind.getId() == id) {
+        return kind;
+      }
     }
     return null;
   }
 
   private static class KindGenerator {
-    private int nextId = 1;
     private List<SyntheticKind> kinds = new ArrayList<>();
-
-    private int getNextId() {
-      return nextId++;
-    }
+    private IntSet usedIds = new IntArraySet();
 
     private SyntheticKind register(SyntheticKind kind) {
+      if (!usedIds.add(kind.getId())) {
+        throw new Unreachable("Invalid reuse of synthetic kind id: " + kind.getId());
+      }
       kinds.add(kind);
       return kind;
     }
 
-    SyntheticKind forSingleMethod(String descriptor) {
-      return register(new SyntheticMethodKind(getNextId(), descriptor));
+    SyntheticKind forSingleMethod(int id, String descriptor) {
+      return register(new SyntheticMethodKind(id, descriptor));
     }
 
     // TODO(b/214901256): Remove once fixed.
-    SyntheticKind forNonSharableInstanceClass(String descriptor) {
-      return register(new SyntheticClassKind(getNextId(), descriptor, false));
+    SyntheticKind forNonSharableInstanceClass(int id, String descriptor) {
+      return register(new SyntheticClassKind(id, descriptor, false));
     }
 
-    SyntheticKind forInstanceClass(String descriptor) {
-      return register(new SyntheticClassKind(getNextId(), descriptor, true));
+    SyntheticKind forInstanceClass(int id, String descriptor) {
+      return register(new SyntheticClassKind(id, descriptor, true));
     }
 
-    SyntheticKind forFixedClass(String descriptor) {
-      return register(new SyntheticFixedClassKind(getNextId(), descriptor, false));
+    SyntheticKind forFixedClass(int id, String descriptor) {
+      return register(new SyntheticFixedClassKind(id, descriptor, false));
     }
 
-    SyntheticKind forGlobalClass() {
-      return register(new SyntheticFixedClassKind(getNextId(), "", true));
+    SyntheticKind forGlobalClass(int id) {
+      return register(new SyntheticFixedClassKind(id, "", true));
     }
 
-    SyntheticKind forGlobalClasspathClass() {
-      return register(new SyntheticFixedClassKind(getNextId(), "", false));
+    SyntheticKind forGlobalClasspathClass(int id) {
+      return register(new SyntheticFixedClassKind(id, "", false));
     }
 
     List<SyntheticKind> getAllKinds() {
@@ -321,7 +327,7 @@
         binaryName.lastIndexOf(
             kind.isFixedSuffixSynthetic() ? kind.descriptor : SYNTHETIC_CLASS_SEPARATOR);
     if (index < 0) {
-      throw new Unreachable("Unexpected failure to compute an synthetic prefix");
+      throw new Unreachable("Unexpected failure to compute a synthetic prefix for " + binaryName);
     }
     return binaryName.substring(0, index);
   }
diff --git a/src/test/examples/abstractmethodremoval/keep-rules.txt b/src/test/examples/abstractmethodremoval/keep-rules.txt
deleted file mode 100644
index ec37858..0000000
--- a/src/test/examples/abstractmethodremoval/keep-rules.txt
+++ /dev/null
@@ -1 +0,0 @@
--keep public class abstractmethodremoval.AbstractMethodRemoval { public static void main(...); }
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
index 922f2d3..326b530 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
@@ -25,7 +25,6 @@
   @Parameters(name = "{0}_{1}_{2}_{3}_{5}_{6}")
   public static Collection<String[]> data() {
     String[] tests = {
-        "abstractmethodremoval.AbstractMethodRemoval",
         "arithmetic.Arithmetic",
         "arrayaccess.ArrayAccess",
         "barray.BArray",
diff --git a/src/test/examples/abstractmethodremoval/AbstractMethodRemoval.java b/src/test/java/com/android/tools/r8/examples/abstractmethodremoval/AbstractMethodRemoval.java
similarity index 73%
rename from src/test/examples/abstractmethodremoval/AbstractMethodRemoval.java
rename to src/test/java/com/android/tools/r8/examples/abstractmethodremoval/AbstractMethodRemoval.java
index 1da772d..3ecac10 100644
--- a/src/test/examples/abstractmethodremoval/AbstractMethodRemoval.java
+++ b/src/test/java/com/android/tools/r8/examples/abstractmethodremoval/AbstractMethodRemoval.java
@@ -1,12 +1,12 @@
 // Copyright (c) 2018, the R8 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.
-package abstractmethodremoval;
+package com.android.tools.r8.examples.abstractmethodremoval;
 
-import abstractmethodremoval.a.PackageBase;
-import abstractmethodremoval.a.Public;
-import abstractmethodremoval.b.Impl1;
-import abstractmethodremoval.b.Impl2;
+import com.android.tools.r8.examples.abstractmethodremoval.a.PackageBase;
+import com.android.tools.r8.examples.abstractmethodremoval.a.Public;
+import com.android.tools.r8.examples.abstractmethodremoval.b.Impl1;
+import com.android.tools.r8.examples.abstractmethodremoval.b.Impl2;
 
 public class AbstractMethodRemoval {
 
diff --git a/src/test/java/com/android/tools/r8/examples/abstractmethodremoval/AbstractMethodRemovalTestRunner.java b/src/test/java/com/android/tools/r8/examples/abstractmethodremoval/AbstractMethodRemovalTestRunner.java
new file mode 100644
index 0000000..20cda19
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/examples/abstractmethodremoval/AbstractMethodRemovalTestRunner.java
@@ -0,0 +1,76 @@
+// Copyright (c) 2022, the R8 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.
+package com.android.tools.r8.examples.abstractmethodremoval;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.examples.abstractmethodremoval.a.PackageBase;
+import com.android.tools.r8.examples.abstractmethodremoval.a.Public;
+import com.android.tools.r8.examples.abstractmethodremoval.b.Impl1;
+import com.android.tools.r8.examples.abstractmethodremoval.b.Impl2;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class AbstractMethodRemovalTestRunner extends TestBase {
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  public AbstractMethodRemovalTestRunner(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  private Class<?> getMainClass() {
+    return AbstractMethodRemoval.class;
+  }
+
+  private List<Class<?>> getProgramClasses() {
+    return ImmutableList.of(
+        getMainClass(), Public.class, PackageBase.class, Impl1.class, Impl2.class);
+  }
+
+  private String getExpected() {
+    return StringUtils.lines(
+        "Impl1.foo(0)",
+        "Impl2.foo(0)",
+        "Impl2.foo(0)",
+        "Impl1.foo(0)",
+        "Impl2.foo(0)",
+        "Impl2.foo(0)");
+  }
+
+  @Test
+  public void testReference() throws Exception {
+    testForRuntime(parameters)
+        .addProgramClasses(getProgramClasses())
+        .run(parameters.getRuntime(), getMainClass())
+        .assertSuccessWithOutput(getExpected());
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addProgramClasses(getProgramClasses())
+        .addKeepMainRule(getMainClass())
+        .setMinApi(parameters.getApiLevel())
+        .run(parameters.getRuntime(), getMainClass())
+        .applyIf(
+            // TODO(b/227302144): The program should not fail after R8.
+            parameters.isDexRuntime()
+                && parameters.asDexRuntime().getVersion().isNewerThanOrEqual(Version.V5_1_1),
+            r -> r.assertFailure(),
+            r -> r.assertSuccessWithOutput(getExpected()));
+  }
+}
diff --git a/src/test/examples/abstractmethodremoval/a/PackageBase.java b/src/test/java/com/android/tools/r8/examples/abstractmethodremoval/a/PackageBase.java
similarity index 84%
rename from src/test/examples/abstractmethodremoval/a/PackageBase.java
rename to src/test/java/com/android/tools/r8/examples/abstractmethodremoval/a/PackageBase.java
index 1075b57..6ca5d44 100644
--- a/src/test/examples/abstractmethodremoval/a/PackageBase.java
+++ b/src/test/java/com/android/tools/r8/examples/abstractmethodremoval/a/PackageBase.java
@@ -1,7 +1,7 @@
 // Copyright (c) 2018, the R8 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.
-package abstractmethodremoval.a;
+package com.android.tools.r8.examples.abstractmethodremoval.a;
 
 public abstract class PackageBase {
   abstract void foo(int i);
diff --git a/src/test/examples/abstractmethodremoval/a/Public.java b/src/test/java/com/android/tools/r8/examples/abstractmethodremoval/a/Public.java
similarity index 83%
rename from src/test/examples/abstractmethodremoval/a/Public.java
rename to src/test/java/com/android/tools/r8/examples/abstractmethodremoval/a/Public.java
index 492ab87..db5cdd9 100644
--- a/src/test/examples/abstractmethodremoval/a/Public.java
+++ b/src/test/java/com/android/tools/r8/examples/abstractmethodremoval/a/Public.java
@@ -1,7 +1,7 @@
 // Copyright (c) 2018, the R8 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.
-package abstractmethodremoval.a;
+package com.android.tools.r8.examples.abstractmethodremoval.a;
 
 public abstract class Public extends PackageBase {
   @Override
diff --git a/src/test/examples/abstractmethodremoval/b/Impl1.java b/src/test/java/com/android/tools/r8/examples/abstractmethodremoval/b/Impl1.java
similarity index 72%
rename from src/test/examples/abstractmethodremoval/b/Impl1.java
rename to src/test/java/com/android/tools/r8/examples/abstractmethodremoval/b/Impl1.java
index bfdf4d1..a1b5f7a 100644
--- a/src/test/examples/abstractmethodremoval/b/Impl1.java
+++ b/src/test/java/com/android/tools/r8/examples/abstractmethodremoval/b/Impl1.java
@@ -1,9 +1,9 @@
 // Copyright (c) 2018, the R8 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.
-package abstractmethodremoval.b;
+package com.android.tools.r8.examples.abstractmethodremoval.b;
 
-import abstractmethodremoval.a.Public;
+import com.android.tools.r8.examples.abstractmethodremoval.a.Public;
 
 public class Impl1 extends Public {
   @Override
diff --git a/src/test/examples/abstractmethodremoval/b/Impl2.java b/src/test/java/com/android/tools/r8/examples/abstractmethodremoval/b/Impl2.java
similarity index 72%
rename from src/test/examples/abstractmethodremoval/b/Impl2.java
rename to src/test/java/com/android/tools/r8/examples/abstractmethodremoval/b/Impl2.java
index a92e2a1..b21c5da 100644
--- a/src/test/examples/abstractmethodremoval/b/Impl2.java
+++ b/src/test/java/com/android/tools/r8/examples/abstractmethodremoval/b/Impl2.java
@@ -1,9 +1,9 @@
 // Copyright (c) 2018, the R8 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.
-package abstractmethodremoval.b;
+package com.android.tools.r8.examples.abstractmethodremoval.b;
 
-import abstractmethodremoval.a.Public;
+import com.android.tools.r8.examples.abstractmethodremoval.a.Public;
 
 public class Impl2 extends Public {
   @Override
diff --git a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAbstractMethodRemovalTest.java b/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAbstractMethodRemovalTest.java
deleted file mode 100644
index b008254..0000000
--- a/src/test/java/com/android/tools/r8/shaking/examples/TreeShakingAbstractMethodRemovalTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2018, the R8 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.
-package com.android.tools.r8.shaking.examples;
-
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.shaking.TreeShakingTest;
-import com.google.common.collect.ImmutableList;
-import java.util.List;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class TreeShakingAbstractMethodRemovalTest extends TreeShakingTest {
-
-  @Parameters(name = "mode:{0}-{1} minify:{2}")
-  public static List<Object[]> data() {
-    return defaultTreeShakingParameters();
-  }
-
-  public TreeShakingAbstractMethodRemovalTest(
-      Frontend frontend, TestParameters parameters, MinifyMode minify) {
-    super(frontend, parameters, minify);
-  }
-
-  @Override
-  protected String getName() {
-    return "examples/abstractmethodremoval";
-  }
-
-  @Override
-  protected String getMainClass() {
-    return "abstractmethodremoval.AbstractMethodRemoval";
-  }
-
-  @Test
-  public void test() throws Exception {
-    runTest(
-        null,
-        null,
-        null,
-        ImmutableList.of("src/test/examples/abstractmethodremoval/keep-rules.txt"));
-  }
-}