Version 2.0.48

Manual cherry pick, with lines extracted from:
https://r8-review.googlesource.com/c/r8/+/48306
https://r8-review.googlesource.com/c/r8/+/48388

Bug:150927764
Change-Id: I8a40b742035352b3375acf13948fed56d18c74a1
diff --git a/src/main/java/com/android/tools/r8/naming/Minifier.java b/src/main/java/com/android/tools/r8/naming/Minifier.java
index eb3a614..185554c 100644
--- a/src/main/java/com/android/tools/r8/naming/Minifier.java
+++ b/src/main/java/com/android/tools/r8/naming/Minifier.java
@@ -217,11 +217,13 @@
 
     final AppView<?> appView;
     private final DexItemFactory factory;
+    private final boolean desugaredLibraryRenaming;
 
     public MinifierMemberNamingStrategy(AppView<?> appView) {
       super(appView.options().getProguardConfiguration().getObfuscationDictionary(), false);
       this.appView = appView;
       this.factory = appView.dexItemFactory();
+      this.desugaredLibraryRenaming = appView.rewritePrefix.isRewriting();
     }
 
     @Override
@@ -264,6 +266,9 @@
           || appView.rootSet().mayNotBeMinified(method.method, appView)) {
         return method.method.name;
       }
+      if (desugaredLibraryRenaming && method.isLibraryMethodOverride().isTrue()) {
+        return method.method.name;
+      }
       return null;
     }
 
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 6b687c8..cdbeeb4 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -55,6 +55,7 @@
 import com.android.tools.r8.ir.code.InvokeVirtual;
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.ir.desugar.DesugaredLibraryAPIConverter;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryWrapperSynthesizer;
 import com.android.tools.r8.ir.desugar.LambdaDescriptor;
 import com.android.tools.r8.logging.Log;
 import com.android.tools.r8.origin.Origin;
@@ -1641,6 +1642,20 @@
         }
       }
     }
+    // If we are compiling with desugared library, then mark all instantiated wrapper methods
+    // as library override. This is a temporary hack for Android Studio 4.0. In subsequent
+    // releases of R8, wrapper synthesis is moved to the enqueuer and does not suffer from this
+    // problem.
+    if (!appView.options().desugaredLibraryConfiguration.getRewritePrefix().isEmpty()
+        && instantiatedClass.accessFlags.isSynthetic()
+        && DesugaredLibraryWrapperSynthesizer.isSynthesizedWrapper(instantiatedClass.type)) {
+      for (DexEncodedMethod method : instantiatedClass.methods()) {
+        ResolutionResult resolution =
+            appView.appInfo().resolveMethod(instantiatedClass, method.method);
+        markResolutionAsLive(instantiatedClass, resolution);
+        markOverridesAsLibraryMethodOverrides(method.method, instantiatedClass);
+      }
+    }
   }
 
   private void markLibraryAndClasspathMethodOverridesAsLive(
@@ -1653,6 +1668,7 @@
       ResolutionResult firstResolution =
           appView.appInfo().resolveMethod(instantiatedClass, method.method);
       markResolutionAsLive(libraryClass, firstResolution);
+      markOverridesAsLibraryMethodOverrides(method.method, instantiatedClass);
 
       // Due to API conversion, some overrides can be hidden since they will be rewritten. See
       // class comment of DesugaredLibraryAPIConverter and vivifiedType logic.
@@ -1667,9 +1683,9 @@
         ResolutionResult secondResolution =
             appView.appInfo().resolveMethod(instantiatedClass, methodToResolve);
         markResolutionAsLive(libraryClass, secondResolution);
+        markOverridesAsLibraryMethodOverrides(methodToResolve, instantiatedClass);
       }
 
-      markOverridesAsLibraryMethodOverrides(method, instantiatedClass);
     }
   }
 
@@ -1686,13 +1702,13 @@
   }
 
   private void markOverridesAsLibraryMethodOverrides(
-      DexEncodedMethod libraryMethod, DexProgramClass instantiatedClass) {
+      DexMethod libraryMethod, DexProgramClass instantiatedClass) {
     Set<DexProgramClass> visited = SetUtils.newIdentityHashSet(instantiatedClass);
     Deque<DexProgramClass> worklist = DequeUtils.newArrayDeque(instantiatedClass);
     while (!worklist.isEmpty()) {
       DexProgramClass clazz = worklist.removeFirst();
       assert visited.contains(clazz);
-      DexEncodedMethod libraryMethodOverride = clazz.lookupVirtualMethod(libraryMethod.method);
+      DexEncodedMethod libraryMethodOverride = clazz.lookupVirtualMethod(libraryMethod);
       if (libraryMethodOverride != null) {
         if (libraryMethodOverride.isLibraryMethodOverride().isTrue()) {
           continue;
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/FunctionConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/FunctionConversionTest.java
index 1dfbc73..59a0cbd 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/FunctionConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/FunctionConversionTest.java
@@ -4,16 +4,15 @@
 
 package com.android.tools.r8.desugar.desugaredlibrary.conversiontests;
 
-import static junit.framework.TestCase.assertEquals;
-
-import com.android.tools.r8.TestRuntime.DexRuntime;
-import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
 import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
-import com.android.tools.r8.ir.desugar.DesugaredLibraryWrapperSynthesizer;
+import com.android.tools.r8.desugar.desugaredlibrary.conversiontests.FunctionConversionTest.Executor.Object1;
+import com.android.tools.r8.desugar.desugaredlibrary.conversiontests.FunctionConversionTest.Executor.Object2;
+import com.android.tools.r8.desugar.desugaredlibrary.conversiontests.FunctionConversionTest.Executor.Object3;
 import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.StringUtils;
-import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
 import java.nio.file.Path;
 import java.util.List;
 import java.util.function.BiFunction;
@@ -25,83 +24,93 @@
 import java.util.function.IntSupplier;
 import java.util.function.LongConsumer;
 import java.util.function.LongSupplier;
-import java.util.stream.Collectors;
-import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.BeforeClass;
 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 FunctionConversionTest extends DesugaredLibraryTestBase {
 
-  @Test
-  public void testFunctionComposition() throws Exception {
-    Path customLib = testForD8().addProgramClasses(CustomLibClass.class).compile().writeToZip();
-    testForD8()
-        .setMinApi(AndroidApiLevel.B)
-        .addProgramClasses(
-            Executor.class, Executor.Object1.class, Executor.Object2.class, Executor.Object3.class)
-        .addLibraryClasses(CustomLibClass.class)
-        .enableCoreLibraryDesugaring(AndroidApiLevel.B)
-        .compile()
-        .inspect(this::assertSingleWrappers)
-        .addDesugaredCoreLibraryRunClassPath(this::buildDesugaredLibrary, AndroidApiLevel.B)
-        .addRunClasspathFiles(customLib)
-        .run(new DexRuntime(DexVm.ART_9_0_0_HOST), Executor.class)
-        .assertSuccessWithOutput(
-            StringUtils.lines("Object1 Object2 Object3", "2", "false", "3", "true", "5", "42.0"));
+  private final TestParameters parameters;
+  private final boolean shrinkDesugaredLibrary;
+  private static final AndroidApiLevel MIN_SUPPORTED = AndroidApiLevel.N;
+  private static final String EXPECTED_RESULT =
+      StringUtils.lines(" true true true", "2", "false", "3", "true", "5", "42.0");
+  private static Path CUSTOM_LIB;
+
+  @Parameters(name = "{0}, shrinkDesugaredLibrary: {1}")
+  public static List<Object[]> data() {
+    return buildParameters(
+        getTestParameters()
+            .withDexRuntimesStartingFromIncluding(Version.V7_0_0)
+            .withApiLevelsEndingAtExcluding(AndroidApiLevel.M)
+            .build(),
+        BooleanUtils.values());
   }
 
-  private void assertSingleWrappers(CodeInspector i) {
-    List<FoundClassSubject> intSupplierWrapperClasses =
-        i.allClasses().stream()
-            .filter(c -> c.getOriginalName().contains("IntSupplier"))
-            .collect(Collectors.toList());
-    assertEquals(
-        "Expected 1 IntSupplier wrapper but got " + intSupplierWrapperClasses,
-        1,
-        intSupplierWrapperClasses.size());
+  public FunctionConversionTest(TestParameters parameters, boolean shrinkDesugaredLibrary) {
+    this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
+    this.parameters = parameters;
+  }
 
-    List<FoundClassSubject> doubleSupplierWrapperClasses =
-        i.allClasses().stream()
-            .filter(c -> c.getOriginalName().contains("DoubleSupplier"))
-            .collect(Collectors.toList());
-    assertEquals(
-        "Expected 1 DoubleSupplier wrapper but got " + doubleSupplierWrapperClasses,
-        1,
-        doubleSupplierWrapperClasses.size());
+  @BeforeClass
+  public static void compileCustomLib() throws Exception {
+    CUSTOM_LIB =
+        testForD8(getStaticTemp())
+            .addProgramClasses(CustomLibClass.class)
+            .setMinApi(MIN_SUPPORTED)
+            .compile()
+            .writeToZip();
   }
 
   @Test
-  public void testWrapperWithChecksum() throws Exception {
+  public void testFunctionCompositionD8() throws Exception {
+    KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
     testForD8()
+        .setMinApi(parameters.getApiLevel())
         .addProgramClasses(
             Executor.class, Executor.Object1.class, Executor.Object2.class, Executor.Object3.class)
         .addLibraryClasses(CustomLibClass.class)
-        .setMinApi(AndroidApiLevel.B)
-        .enableCoreLibraryDesugaring(AndroidApiLevel.B)
-        .setIncludeClassesChecksum(true) // Compilation fails if some classes are missing checksum.
+        .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
         .compile()
-        .inspect(
-            inspector -> {
-              Assert.assertEquals(
-                  8,
-                  inspector.allClasses().stream()
-                      .filter(
-                          clazz ->
-                              clazz
-                                  .getFinalName()
-                                  .contains(DesugaredLibraryWrapperSynthesizer.TYPE_WRAPPER_SUFFIX))
-                      .count());
-              Assert.assertEquals(
-                  6,
-                  inspector.allClasses().stream()
-                      .filter(
-                          clazz ->
-                              clazz
-                                  .getFinalName()
-                                  .contains(
-                                      DesugaredLibraryWrapperSynthesizer
-                                          .VIVIFIED_TYPE_WRAPPER_SUFFIX))
-                      .count());
-            });
+        .addDesugaredCoreLibraryRunClassPath(
+            this::buildDesugaredLibrary,
+            parameters.getApiLevel(),
+            keepRuleConsumer.get(),
+            shrinkDesugaredLibrary)
+        .addRunClasspathFiles(CUSTOM_LIB)
+        .run(parameters.getRuntime(), Executor.class)
+        .assertSuccessWithOutput(EXPECTED_RESULT);
+  }
+
+  @Test
+  public void testFunctionCompositionR8() throws Exception {
+    // The test pass only if -ea is not set. This test has been backported due to a problem in R8
+    // 2.0. This problem has been fixed in R8 2.1 / Android Studio 4.1.
+    try {
+      assert false;
+    } catch (AssertionError e) {
+      Assume.assumeTrue(false);
+    }
+    KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
+    testForR8(parameters.getBackend())
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Executor.class)
+        .addProgramClasses(Executor.class, Object1.class, Object2.class, Object3.class)
+        .addLibraryClasses(CustomLibClass.class)
+        .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
+        .compile()
+        .addDesugaredCoreLibraryRunClassPath(
+            this::buildDesugaredLibrary,
+            parameters.getApiLevel(),
+            keepRuleConsumer.get(),
+            shrinkDesugaredLibrary)
+        .addRunClasspathFiles(CUSTOM_LIB)
+        .run(parameters.getRuntime(), Executor.class)
+        .assertSuccessWithOutput(EXPECTED_RESULT);
   }
 
   static class Executor {
@@ -145,11 +154,12 @@
 
       @Override
       public String toString() {
-        return field.field.getClass().getSimpleName()
+        return " "
+            + (field.field.getClass() == Object1.class)
             + " "
-            + field.getClass().getSimpleName()
+            + (field.getClass() == Object2.class)
             + " "
-            + getClass().getSimpleName();
+            + (getClass() == Object3.class);
       }
     }
   }