Always generate the big wrapper

Bug: 150442579
Change-Id: Ie96fce062232531f94864353275e923e74069520
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/DesugaredLibraryConversionWrapperAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/DesugaredLibraryConversionWrapperAnalysis.java
index c85439b..d8d48a2 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/DesugaredLibraryConversionWrapperAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/DesugaredLibraryConversionWrapperAnalysis.java
@@ -121,9 +121,8 @@
       registration.accept(virtualMethod);
     }
     DexProgramClass reverseWrapper = wrappersToReverseMap.get(wrapper);
-    if (reverseWrapper != null) {
-      registration.accept(getConvertMethod(reverseWrapper));
-    }
+    assert reverseWrapper != null;
+    registration.accept(getConvertMethod(reverseWrapper));
     return this;
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
index 069015f..3527f62 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
@@ -20,7 +20,6 @@
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProgramClass;
-import com.android.tools.r8.graph.DexProgramClass.ChecksumSupplier;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DexTypeList;
@@ -120,12 +119,6 @@
     this.vivifiedSourceFile = appView.dexItemFactory().createString("vivified");
   }
 
-  public static boolean isSynthesizedWrapper(DexType type) {
-    // Slow path, but more convenient since no instance is needed. Use hasSynthesized(DexType) when
-    // possible.
-    return type.descriptor.toString().startsWith("L" + WRAPPER_PREFIX);
-  }
-
   boolean hasSynthesized(DexType type) {
     return type.descriptor.startsWith(dexWrapperPrefix);
   }
@@ -139,10 +132,14 @@
   }
 
   DexType getTypeWrapper(DexType type) {
+    // Force create the reverse wrapper.
+    getWrapper(type, VIVIFIED_TYPE_WRAPPER_SUFFIX, vivifiedTypeWrappers);
     return getWrapper(type, TYPE_WRAPPER_SUFFIX, typeWrappers);
   }
 
   DexType getVivifiedTypeWrapper(DexType type) {
+    // Force create the reverse wrapper.
+    getWrapper(type, TYPE_WRAPPER_SUFFIX, typeWrappers);
     return getWrapper(type, VIVIFIED_TYPE_WRAPPER_SUFFIX, vivifiedTypeWrappers);
   }
 
@@ -249,25 +246,10 @@
         new DexEncodedMethod[] {synthesizeConstructor(wrapperField.field), conversionMethod},
         virtualMethods,
         factory.getSkipNameValidationForTesting(),
-        getChecksumSupplier(this, clazz.type),
+        DexProgramClass::checksumFromType,
         Collections.emptyList());
   }
 
-  private ChecksumSupplier getChecksumSupplier(
-      DesugaredLibraryWrapperSynthesizer synthesizer, DexType keyType) {
-    return clazz -> {
-      // The synthesized type wrappers are constructed lazily, so their lookup must be delayed
-      // until the point the checksum is requested (at write time). The presence of a wrapper
-      // affects the implementation of the conversion functions, so they must be accounted for in
-      // the checksum.
-      boolean hasWrapper = synthesizer.typeWrappers.containsKey(keyType);
-      boolean hasViviWrapper = synthesizer.vivifiedTypeWrappers.containsKey(keyType);
-      return ((long) clazz.type.hashCode())
-          + 7 * (long) Boolean.hashCode(hasWrapper)
-          + 11 * (long) Boolean.hashCode(hasViviWrapper);
-    };
-  }
-
   private DexEncodedMethod[] synthesizeVirtualMethodsForVivifiedTypeWrapper(
       DexClass dexClass, DexEncodedField wrapperField) {
     List<DexEncodedMethod> dexMethods = allImplementedMethods(dexClass);
@@ -284,7 +266,14 @@
     Set<DexMethod> finalMethods = Sets.newIdentityHashSet();
     for (DexEncodedMethod dexEncodedMethod : dexMethods) {
       DexClass holderClass = appView.definitionFor(dexEncodedMethod.method.holder);
-      assert holderClass != null;
+      boolean isInterface;
+      if (holderClass == null) {
+        assert appView.options().desugaredLibraryConfiguration.getEmulateLibraryInterface()
+            .containsValue(dexEncodedMethod.method.holder);
+        isInterface = true;
+      } else {
+        isInterface = holderClass.isInterface();
+      }
       DexMethod methodToInstall =
           factory.createMethod(
               wrapperField.field.holder,
@@ -302,7 +291,7 @@
                     methodToInstall,
                     wrapperField.field,
                     converter,
-                    holderClass.isInterface())
+                isInterface)
                 .generateCfCode();
       }
       DexEncodedMethod newDexEncodedMethod =
@@ -585,23 +574,25 @@
 
   private DexEncodedMethod generateTypeConversion(DexType type, DexType typeWrapperType) {
     DexType reverse = vivifiedTypeWrappers.get(type);
+    assert reverse != null;
     return synthesizeConversionMethod(
         typeWrapperType,
         type,
         type,
         vivifiedTypeFor(type),
-        reverse == null ? null : wrappedValueField(reverse, vivifiedTypeFor(type)));
+        wrappedValueField(reverse, vivifiedTypeFor(type)));
   }
 
   private DexEncodedMethod generateVivifiedTypeConversion(
       DexType type, DexType vivifiedTypeWrapperType) {
     DexType reverse = typeWrappers.get(type);
+    assert reverse != null;
     return synthesizeConversionMethod(
         vivifiedTypeWrapperType,
         type,
         vivifiedTypeFor(type),
         type,
-        reverse == null ? null : wrappedValueField(reverse, type));
+        wrappedValueField(reverse, type));
   }
 
   private DexEncodedMethod synthesizeConversionMethod(
@@ -609,7 +600,7 @@
       DexType type,
       DexType argType,
       DexType returnType,
-      DexField reverseFieldOrNull) {
+      DexField reverseField) {
     DexMethod method =
         factory.createMethod(
             holder, factory.createProto(returnType, argType), factory.convertMethodName);
@@ -629,7 +620,7 @@
           new APIConverterWrapperConversionCfCodeProvider(
                   appView,
                   argType,
-                  reverseFieldOrNull,
+                  reverseField,
                   factory.createField(holder, returnType, factory.wrapperFieldName))
               .generateCfCode();
     }
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/DesugaredLibraryAPIConversionCfCodeProvider.java b/src/main/java/com/android/tools/r8/ir/synthetic/DesugaredLibraryAPIConversionCfCodeProvider.java
index 422bc2f..50885dc 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/DesugaredLibraryAPIConversionCfCodeProvider.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/DesugaredLibraryAPIConversionCfCodeProvider.java
@@ -253,20 +253,18 @@
       instructions.add(new CfReturn(ValueType.OBJECT));
       instructions.add(nullDest);
 
-      // This part is skipped if there is no reverse wrapper.
       // if (arg instanceOf ReverseWrapper) { return ((ReverseWrapper) arg).wrapperField};
-      if (reverseWrapperField != null) {
-        CfLabel unwrapDest = new CfLabel();
-        instructions.add(new CfLoad(ValueType.fromDexType(argType), 0));
-        instructions.add(new CfInstanceOf(reverseWrapperField.holder));
-        instructions.add(new CfIf(If.Type.EQ, ValueType.INT, unwrapDest));
-        instructions.add(new CfLoad(ValueType.fromDexType(argType), 0));
-        instructions.add(new CfCheckCast(reverseWrapperField.holder));
-        instructions.add(
-            new CfFieldInstruction(Opcodes.GETFIELD, reverseWrapperField, reverseWrapperField));
-        instructions.add(new CfReturn(ValueType.fromDexType(reverseWrapperField.type)));
-        instructions.add(unwrapDest);
-      }
+      assert reverseWrapperField != null;
+      CfLabel unwrapDest = new CfLabel();
+      instructions.add(new CfLoad(ValueType.fromDexType(argType), 0));
+      instructions.add(new CfInstanceOf(reverseWrapperField.holder));
+      instructions.add(new CfIf(If.Type.EQ, ValueType.INT, unwrapDest));
+      instructions.add(new CfLoad(ValueType.fromDexType(argType), 0));
+      instructions.add(new CfCheckCast(reverseWrapperField.holder));
+      instructions.add(
+          new CfFieldInstruction(Opcodes.GETFIELD, reverseWrapperField, reverseWrapperField));
+      instructions.add(new CfReturn(ValueType.fromDexType(reverseWrapperField.type)));
+      instructions.add(unwrapDest);
 
       // return new Wrapper(wrappedValue);
       instructions.add(new CfNew(wrapperField.holder));
@@ -317,6 +315,7 @@
 
   public static class APIConverterThrowRuntimeExceptionCfCodeProvider
       extends SyntheticCfCodeProvider {
+
     DexString message;
 
     public APIConverterThrowRuntimeExceptionCfCodeProvider(
diff --git a/src/main/java/com/android/tools/r8/utils/ProgramClassCollection.java b/src/main/java/com/android/tools/r8/utils/ProgramClassCollection.java
index d602a51..3681a77 100644
--- a/src/main/java/com/android/tools/r8/utils/ProgramClassCollection.java
+++ b/src/main/java/com/android/tools/r8/utils/ProgramClassCollection.java
@@ -4,13 +4,10 @@
 package com.android.tools.r8.utils;
 
 import com.android.tools.r8.dex.ApplicationReader.ProgramClassConflictResolver;
-import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.DuplicateTypesDiagnostic;
 import com.android.tools.r8.graph.ClassKind;
-import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.desugar.DesugaredLibraryWrapperSynthesizer;
 import com.android.tools.r8.references.Reference;
 import com.google.common.collect.ImmutableList;
 import java.util.List;
@@ -85,9 +82,6 @@
 
   private static DexProgramClass mergeClasses(
       Reporter reporter, DexProgramClass a, DexProgramClass b) {
-    if (DesugaredLibraryWrapperSynthesizer.isSynthesizedWrapper(a.type)) {
-      return mergeWrappers(a, b);
-    }
     if (a.type.isD8R8SynthesizedClassType()) {
       assert assertEqualClasses(a, b);
       return a;
@@ -100,22 +94,4 @@
     assert a.directMethods().size() == b.directMethods().size();
     return true;
   }
-
-  private static DexProgramClass mergeWrappers(DexProgramClass a, DexProgramClass b) {
-    DexEncodedMethod aMethod = findConversionMethod(a);
-    DexEncodedMethod bMethod = findConversionMethod(b);
-    return aMethod.getCode().estimatedSizeForInlining()
-            > bMethod.getCode().estimatedSizeForInlining()
-        ? a
-        : b;
-  }
-
-  private static DexEncodedMethod findConversionMethod(DexProgramClass clazz) {
-    for (DexEncodedMethod dexEncodedMethod : clazz.directMethods()) {
-      if (!dexEncodedMethod.isInstanceInitializer()) {
-        return dexEncodedMethod;
-      }
-    }
-    throw new CompilationError("A wrapper should have a conversion method.");
-  }
 }
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 687a673..3d1b999 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,12 @@
 
 package com.android.tools.r8.desugar.desugaredlibrary.conversiontests;
 
-import static junit.framework.TestCase.assertEquals;
-
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
 import com.android.tools.r8.ir.desugar.DesugaredLibraryWrapperSynthesizer;
 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,7 +21,6 @@
 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;
@@ -75,7 +70,6 @@
         .addLibraryClasses(CustomLibClass.class)
         .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
         .compile()
-        .inspect(this::assertSingleWrappers)
         .addDesugaredCoreLibraryRunClassPath(
             this::buildDesugaredLibrary,
             parameters.getApiLevel(),
@@ -107,26 +101,6 @@
         .assertSuccessWithOutput(EXPECTED_RESULT);
   }
 
-  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());
-
-    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());
-  }
-
   @Test
   public void testWrapperWithChecksum() throws Exception {
     Assume.assumeTrue(
@@ -142,7 +116,7 @@
         .inspect(
             inspector -> {
               Assert.assertEquals(
-                  8,
+                  9,
                   inspector.allClasses().stream()
                       .filter(
                           clazz ->
@@ -151,7 +125,7 @@
                                   .contains(DesugaredLibraryWrapperSynthesizer.TYPE_WRAPPER_SUFFIX))
                       .count());
               Assert.assertEquals(
-                  6,
+                  9,
                   inspector.allClasses().stream()
                       .filter(
                           clazz ->