Revert "Delegate wrapper conversion to subtypes"

This reverts commit f9bca89651809f9c0fd01067ec48f126d41b8512.

Reason for revert: Bot failure b/237563869.

Change-Id: Ifb61aae9996a2bd4bd70e848cdc4c734362a5529
diff --git a/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriteDescription.java b/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriteDescription.java
index 2b46e36..137ac12 100644
--- a/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriteDescription.java
+++ b/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriteDescription.java
@@ -17,6 +17,8 @@
 
   private static final Set<String> ENUM_WRAP_CONVERT_OWNER =
       ImmutableSet.of(
+          "j$/nio/file/StandardOpenOption",
+          "j$/nio/file/LinkOption",
           "j$/nio/file/attribute/PosixFilePermission",
           "j$/util/stream/Collector$Characteristics");
   private static final Set<String> WRAP_CONVERT_OWNER =
@@ -25,14 +27,18 @@
           "j$/nio/file/spi/FileTypeDetector",
           "j$/nio/file/Path",
           "j$/nio/file/WatchEvent",
-          "j$/nio/file/OpenOption");
+          "j$/nio/file/attribute/BasicFileAttributes",
+          "j$/nio/file/attribute/BasicFileAttributeView",
+          "j$/nio/file/attribute/FileOwnerAttributeView",
+          "j$/nio/file/attribute/PosixFileAttributes",
+          "j$/nio/file/attribute/PosixFileAttributeView");
 
   static Map<String, String> getJavaWrapConvertOwnerMap() {
-    return computeConvertOwnerMap("$Wrapper");
+    return computeConvertOwnerMap("$VivifiedWrapper");
   }
 
   static Map<String, String> getJ$WrapConvertOwnerMap() {
-    return computeConvertOwnerMap("$VivifiedWrapper");
+    return computeConvertOwnerMap("$Wrapper");
   }
 
   private static HashMap<String, String> computeConvertOwnerMap(String suffix) {
diff --git a/src/library_desugar/java/j$/nio/file/OpenOption.java b/src/library_desugar/java/j$/nio/file/OpenOption.java
index a22eb7c..8b063d1 100644
--- a/src/library_desugar/java/j$/nio/file/OpenOption.java
+++ b/src/library_desugar/java/j$/nio/file/OpenOption.java
@@ -4,12 +4,4 @@
 
 package j$.nio.file;
 
-public class OpenOption {
-  public static java.nio.file.OpenOption wrap_convert(j$.nio.file.OpenOption option) {
-    return null;
-  }
-
-  public static j$.nio.file.OpenOption wrap_convert(java.nio.file.OpenOption option) {
-    return null;
-  }
-}
+public class OpenOption {}
diff --git a/src/library_desugar/java/j$/nio/file/Path.java b/src/library_desugar/java/j$/nio/file/Path.java
index 781ab5f..cb01ec0 100644
--- a/src/library_desugar/java/j$/nio/file/Path.java
+++ b/src/library_desugar/java/j$/nio/file/Path.java
@@ -6,7 +6,7 @@
 
 public class Path {
 
-  public static j$.nio.file.Path wrap_convert(java.nio.file.Path path) {
+  public static j$.nio.file.Path inverted_wrap_convert(java.nio.file.Path path) {
     return null;
   }
 }
diff --git a/src/library_desugar/java/j$/nio/file/StandardOpenOption.java b/src/library_desugar/java/j$/nio/file/StandardOpenOption.java
new file mode 100644
index 0000000..a65da37
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/StandardOpenOption.java
@@ -0,0 +1,18 @@
+// 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 j$.nio.file;
+
+public class StandardOpenOption extends OpenOption {
+
+  public static java.nio.file.StandardOpenOption wrap_convert(
+      j$.nio.file.StandardOpenOption option) {
+    return null;
+  }
+
+  public static j$.nio.file.StandardOpenOption wrap_convert(
+      java.nio.file.StandardOpenOption option) {
+    return null;
+  }
+}
diff --git a/src/library_desugar/java/j$/nio/file/spi/FileSystemProvider.java b/src/library_desugar/java/j$/nio/file/spi/FileSystemProvider.java
index 8db22b3..38152b3 100644
--- a/src/library_desugar/java/j$/nio/file/spi/FileSystemProvider.java
+++ b/src/library_desugar/java/j$/nio/file/spi/FileSystemProvider.java
@@ -5,8 +5,7 @@
 package j$.nio.file.spi;
 
 public class FileSystemProvider {
-  public static java.nio.file.spi.FileSystemProvider inverted_wrap_convert(
-      j$.nio.file.spi.FileSystemProvider provider) {
+  public static java.nio.file.spi.FileSystemProvider wrap_convert(FileSystemProvider provider) {
     // Rewritten in ASM to the wrapper method.
     return null;
   }
diff --git a/src/library_desugar/java/java/adapter/HybridFileSystemProvider.java b/src/library_desugar/java/java/adapter/HybridFileSystemProvider.java
index 5909b09..d02344d 100644
--- a/src/library_desugar/java/java/adapter/HybridFileSystemProvider.java
+++ b/src/library_desugar/java/java/adapter/HybridFileSystemProvider.java
@@ -27,7 +27,7 @@
       Class.forName("java.nio.file.FileSystems");
       j$.nio.file.FileSystem fileSystem = FileSystems.getDefault();
       j$.nio.file.spi.FileSystemProvider provider = fileSystem.provider();
-      return j$.nio.file.spi.FileSystemProvider.inverted_wrap_convert(provider);
+      return j$.nio.file.spi.FileSystemProvider.wrap_convert(provider);
     } catch (ClassNotFoundException ignored) {
       // We reach this path is API < 26.
     }
diff --git a/src/library_desugar/java/java/adapter/HybridFileTypeDetector.java b/src/library_desugar/java/java/adapter/HybridFileTypeDetector.java
index da93736..af2c8f7 100644
--- a/src/library_desugar/java/java/adapter/HybridFileTypeDetector.java
+++ b/src/library_desugar/java/java/adapter/HybridFileTypeDetector.java
@@ -29,7 +29,7 @@
   static class PlatformFileTypeDetector extends FileTypeDetector {
     @Override
     public String probeContentType(Path path) throws IOException {
-      return j$.nio.file.Files.probeContentType(j$.nio.file.Path.wrap_convert(path));
+      return j$.nio.file.Files.probeContentType(j$.nio.file.Path.inverted_wrap_convert(path));
     }
   }
 }
diff --git a/src/library_desugar/java/java/nio/file/FileApiFlips.java b/src/library_desugar/java/java/nio/file/FileApiFlips.java
index b68aeb2..71b172a 100644
--- a/src/library_desugar/java/java/nio/file/FileApiFlips.java
+++ b/src/library_desugar/java/java/nio/file/FileApiFlips.java
@@ -78,7 +78,7 @@
         } catch (ClassCastException cce) {
           throw exceptionOpenOption(cce);
         }
-        convertedSet.add(j$.nio.file.OpenOption.wrap_convert(option));
+        convertedSet.add(OpenOptionConversions.convert(option));
       }
       return convertedSet;
     }
@@ -90,7 +90,7 @@
         } catch (ClassCastException cce) {
           throw exceptionOpenOption(cce);
         }
-        convertedSet.add(j$.nio.file.OpenOption.wrap_convert(option));
+        convertedSet.add(OpenOptionConversions.convert(option));
       }
       return convertedSet;
     }
diff --git a/src/library_desugar/java/java/nio/file/OpenOptionConversions.java b/src/library_desugar/java/java/nio/file/OpenOptionConversions.java
new file mode 100644
index 0000000..bfe4968
--- /dev/null
+++ b/src/library_desugar/java/java/nio/file/OpenOptionConversions.java
@@ -0,0 +1,35 @@
+// 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 java.nio.file;
+
+import static java.util.ConversionRuntimeException.exception;
+
+public class OpenOptionConversions {
+  public static java.nio.file.OpenOption convert(j$.nio.file.OpenOption option) {
+    if (option == null) {
+      return null;
+    }
+    if (option instanceof j$.nio.file.StandardOpenOption) {
+      return j$.nio.file.StandardOpenOption.wrap_convert((j$.nio.file.StandardOpenOption) option);
+    }
+    if (option instanceof j$.nio.file.LinkOption) {
+      return j$.nio.file.LinkOption.wrap_convert((j$.nio.file.LinkOption) option);
+    }
+    throw exception("java.nio.file.OpenOption", option);
+  }
+
+  public static j$.nio.file.OpenOption convert(java.nio.file.OpenOption option) {
+    if (option == null) {
+      return null;
+    }
+    if (option instanceof java.nio.file.StandardOpenOption) {
+      return j$.nio.file.StandardOpenOption.wrap_convert((java.nio.file.StandardOpenOption) option);
+    }
+    if (option instanceof java.nio.file.LinkOption) {
+      return j$.nio.file.LinkOption.wrap_convert((java.nio.file.LinkOption) option);
+    }
+    throw exception("java.nio.file.OpenOption", option);
+  }
+}
diff --git a/src/library_desugar/java/java/nio/file/attribute/FileAttributeConversions.java b/src/library_desugar/java/java/nio/file/attribute/FileAttributeConversions.java
index c895d52..332c89b 100644
--- a/src/library_desugar/java/java/nio/file/attribute/FileAttributeConversions.java
+++ b/src/library_desugar/java/java/nio/file/attribute/FileAttributeConversions.java
@@ -4,6 +4,8 @@
 
 package java.nio.file.attribute;
 
+import static java.util.ConversionRuntimeException.exception;
+
 public class FileAttributeConversions {
 
   public static java.nio.file.attribute.FileTime convert(j$.nio.file.attribute.FileTime fileTime) {
@@ -20,4 +22,67 @@
     return j$.nio.file.attribute.FileTime.fromMillis(fileTime.toMillis());
   }
 
+  public static java.nio.file.attribute.FileAttributeView convert(
+      j$.nio.file.attribute.FileAttributeView fileAttributeView) {
+    if (fileAttributeView == null) {
+      return null;
+    }
+    if (fileAttributeView instanceof j$.nio.file.attribute.PosixFileAttributeView) {
+      return j$.nio.file.attribute.PosixFileAttributeView.wrap_convert(
+          (j$.nio.file.attribute.PosixFileAttributeView) fileAttributeView);
+    }
+    if (fileAttributeView instanceof j$.nio.file.attribute.FileOwnerAttributeView) {
+      return j$.nio.file.attribute.FileOwnerAttributeView.wrap_convert(
+          (j$.nio.file.attribute.FileOwnerAttributeView) fileAttributeView);
+    }
+    if (fileAttributeView instanceof j$.nio.file.attribute.BasicFileAttributeView) {
+      return j$.nio.file.attribute.BasicFileAttributeView.wrap_convert(
+          (j$.nio.file.attribute.BasicFileAttributeView) fileAttributeView);
+    }
+    throw exception("java.nio.file.attribute.FileAttributeView", fileAttributeView);
+  }
+
+  public static j$.nio.file.attribute.FileAttributeView convert(
+      java.nio.file.attribute.FileAttributeView fileAttributeView) {
+    if (fileAttributeView == null) {
+      return null;
+    }
+    if (fileAttributeView instanceof java.nio.file.attribute.PosixFileAttributeView) {
+      return j$.nio.file.attribute.PosixFileAttributeView.wrap_convert(
+          (java.nio.file.attribute.PosixFileAttributeView) fileAttributeView);
+    }
+    if (fileAttributeView instanceof java.nio.file.attribute.FileOwnerAttributeView) {
+      return j$.nio.file.attribute.FileOwnerAttributeView.wrap_convert(
+          (java.nio.file.attribute.FileOwnerAttributeView) fileAttributeView);
+    }
+    if (fileAttributeView instanceof java.nio.file.attribute.BasicFileAttributeView) {
+      return j$.nio.file.attribute.BasicFileAttributeView.wrap_convert(
+          (java.nio.file.attribute.BasicFileAttributeView) fileAttributeView);
+    }
+    throw exception("java.nio.file.attribute.FileAttributeView", fileAttributeView);
+  }
+
+  public static java.nio.file.attribute.BasicFileAttributes convert(
+      j$.nio.file.attribute.BasicFileAttributes fileAttributes) {
+    if (fileAttributes == null) {
+      return null;
+    }
+    if (fileAttributes instanceof j$.nio.file.attribute.PosixFileAttributes) {
+      return j$.nio.file.attribute.PosixFileAttributes.wrap_convert(
+          (j$.nio.file.attribute.PosixFileAttributes) fileAttributes);
+    }
+    return j$.nio.file.attribute.BasicFileAttributes.wrap_convert(fileAttributes);
+  }
+
+  public static j$.nio.file.attribute.BasicFileAttributes convert(
+      java.nio.file.attribute.BasicFileAttributes fileAttributes) {
+    if (fileAttributes == null) {
+      return null;
+    }
+    if (fileAttributes instanceof java.nio.file.attribute.PosixFileAttributes) {
+      return j$.nio.file.attribute.PosixFileAttributes.wrap_convert(
+          (java.nio.file.attribute.PosixFileAttributes) fileAttributes);
+    }
+    return j$.nio.file.attribute.BasicFileAttributes.wrap_convert(fileAttributes);
+  }
 }
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_path.json b/src/library_desugar/jdk11/desugar_jdk_libs_path.json
index f2e565f..7b767e1 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_path.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_path.json
@@ -132,7 +132,6 @@
         "java.nio.file.spi.FileSystemProvider",
         "java.nio.file.spi.FileTypeDetector",
         "java.nio.file.AccessMode",
-        "java.nio.file.OpenOption",
         "java.nio.file.StandardOpenOption",
         "java.nio.file.LinkOption",
         "java.nio.file.CopyOption",
@@ -146,7 +145,6 @@
         "java.nio.file.attribute.PosixFilePermission",
         "java.nio.file.attribute.BasicFileAttributes",
         "java.nio.file.attribute.PosixFileAttributes",
-        "java.nio.file.attribute.FileAttributeView",
         "java.nio.file.attribute.FileOwnerAttributeView",
         "java.nio.file.attribute.PosixFileAttributeView",
         "java.nio.file.attribute.BasicFileAttributeView"
@@ -159,7 +157,10 @@
         ]
       },
       "custom_conversion": {
-        "java.nio.file.attribute.FileTime": "java.nio.file.attribute.FileAttributeConversions"
+        "java.nio.file.OpenOption": "java.nio.file.OpenOptionConversions",
+        "java.nio.file.attribute.FileTime": "java.nio.file.attribute.FileAttributeConversions",
+        "java.nio.file.attribute.BasicFileAttributes": "java.nio.file.attribute.FileAttributeConversions",
+        "java.nio.file.attribute.FileAttributeView": "java.nio.file.attribute.FileAttributeConversions"
       }
     },
     {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java
index 41ab157..d28ccaf 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java
@@ -46,7 +46,6 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.IdentityHashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.function.BiFunction;
@@ -364,12 +363,7 @@
     }
     assert context.isNotProgramClass();
     Iterable<DexMethod> methods =
-        appView
-            .options()
-            .machineDesugaredLibrarySpecification
-            .getWrappers()
-            .get(context.type)
-            .getMethods();
+        appView.options().machineDesugaredLibrarySpecification.getWrappers().get(context.type);
     assert methods != null;
     ClasspathOrLibraryClass classpathOrLibraryContext = context.asClasspathOrLibraryClass();
     DexType type = context.type;
@@ -480,24 +474,13 @@
             eventConsumer::acceptWrapperClasspathClass);
   }
 
-  private void synthesizeProgramConversionMethod(
+  private void getExistingProgramConversionMethod(
       SyntheticKindSelector kindSelector,
       DexProgramClass context,
-      List<DexType> subwrappers,
       DexClass wrapper,
       DexClass reverseWrapper) {
     DexField wrapperField = getWrapperUniqueField(wrapper);
     DexField reverseWrapperField = getWrapperUniqueField(reverseWrapper);
-    List<DexMethod> subwrapperConvertList = new ArrayList<>();
-    for (DexType subwrapper : subwrappers) {
-      DexClass subwrapperClass = appView.definitionFor(subwrapper);
-      assert subwrapperClass != null;
-      DexProgramClass subwrapperWrapper =
-          getExistingProgramWrapper(
-              subwrapperClass,
-              subwrapperClass.isEnum() ? kinds -> kinds.ENUM_CONVERSION : kindSelector);
-      subwrapperConvertList.add(getConversion(subwrapperWrapper));
-    }
     DexProto proto = factory.createProto(reverseWrapperField.type, wrapperField.type);
     appView
         .getSyntheticItems()
@@ -513,27 +496,14 @@
                     methodBuilder,
                     proto,
                     computeProgramConversionMethodCode(
-                        wrapperField, reverseWrapperField, context, subwrapperConvertList)));
-  }
-
-  private DexMethod getConversion(DexProgramClass subwrapperWrapper) {
-    Iterator<DexEncodedMethod> iterator = subwrapperWrapper.directMethods().iterator();
-    DexEncodedMethod method;
-    do {
-      method = iterator.next();
-    } while (!method.isStatic());
-    assert method.getName() == factory.convertMethodName;
-    return method.getReference();
+                        wrapperField, reverseWrapperField, context)));
   }
 
   private CfCode computeProgramConversionMethodCode(
-      DexField wrapperField,
-      DexField reverseWrapperField,
-      DexClass context,
-      List<DexMethod> subwrapperConvertList) {
+      DexField wrapperField, DexField reverseWrapperField, DexClass context) {
     assert context.isProgramClass();
     return new NullableConversionCfCodeProvider.WrapperConversionCfCodeProvider(
-            appView, reverseWrapperField, wrapperField, subwrapperConvertList)
+            appView, reverseWrapperField, wrapperField)
         .generateCfCode();
   }
 
@@ -665,7 +635,7 @@
     librarySpecification
         .getWrappers()
         .forEach(
-            (type, descriptor) -> {
+            (type, methods) -> {
               DexClass validClassToWrap = getValidClassToWrap(type);
               // In broken set-ups we can end up having a json files containing wrappers of non
               // desugared classes. Such wrappers are not required since the class won't be
@@ -674,25 +644,20 @@
                 if (validClassToWrap.isEnum()) {
                   enumConverter.ensureProgramEnumConversionClass(validClassToWrap, eventConsumer);
                 } else {
-                  validClassesToWrap.put(
-                      validClassToWrap.asProgramClass(), descriptor.getMethods());
-                  synthesizeProgramWrappersWithoutVirtualMethods(
-                      validClassToWrap, descriptor.getSubwrappers(), eventConsumer);
+                  validClassesToWrap.put(validClassToWrap.asProgramClass(), methods);
+                  ensureProgramWrappersWithoutVirtualMethods(validClassToWrap, eventConsumer);
                 }
               }
             });
     validClassesToWrap.forEach(
         (clazz, methods) ->
-            synthesizeProgramWrappersVirtualMethods(
-                clazz, methods, eventConsumer, processingContext));
+            ensureProgramWrappersVirtualMethods(clazz, methods, eventConsumer, processingContext));
   }
 
   // We generate first the two wrappers with the constructor method and the fields, then we
   // the two conversion methods which requires the wrappers to know both fields.
-  private void synthesizeProgramWrappersWithoutVirtualMethods(
-      DexClass context,
-      List<DexType> subwrappers,
-      DesugaredLibraryL8ProgramWrapperSynthesizerEventConsumer eventConsumer) {
+  private void ensureProgramWrappersWithoutVirtualMethods(
+      DexClass context, DesugaredLibraryL8ProgramWrapperSynthesizerEventConsumer eventConsumer) {
     assert eventConsumer != null;
     assert context.isProgramClass();
     DexType type = context.type;
@@ -708,13 +673,13 @@
             vivifiedTypeFor(type),
             programContext,
             eventConsumer);
-    synthesizeProgramConversionMethod(
-        kinds -> kinds.WRAPPER, programContext, subwrappers, wrapper, vivifiedWrapper);
-    synthesizeProgramConversionMethod(
-        kinds -> kinds.VIVIFIED_WRAPPER, programContext, subwrappers, vivifiedWrapper, wrapper);
+    getExistingProgramConversionMethod(
+        kinds -> kinds.WRAPPER, programContext, wrapper, vivifiedWrapper);
+    getExistingProgramConversionMethod(
+        kinds -> kinds.VIVIFIED_WRAPPER, programContext, vivifiedWrapper, wrapper);
   }
 
-  private void synthesizeProgramWrappersVirtualMethods(
+  private void ensureProgramWrappersVirtualMethods(
       DexProgramClass context,
       Iterable<DexMethod> methods,
       CfClassSynthesizerDesugaringEventConsumer eventConsumer,
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanRewritingFlags.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanRewritingFlags.java
index 5c70c34..f17235f 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanRewritingFlags.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanRewritingFlags.java
@@ -15,13 +15,11 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
-import com.google.common.collect.Sets.SetView;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.IdentityHashMap;
 import java.util.Map;
 import java.util.Set;
-import java.util.stream.Collectors;
 
 public class HumanRewritingFlags {
 
@@ -445,7 +443,6 @@
     }
 
     public HumanRewritingFlags build() {
-      validate();
       return new HumanRewritingFlags(
           ImmutableMap.copyOf(rewritePrefix),
           ImmutableSet.copyOf(dontRewritePrefix),
@@ -465,19 +462,5 @@
           ImmutableMap.copyOf(amendLibraryMethod),
           ImmutableMap.copyOf(amendLibraryField));
     }
-
-    private void validate() {
-      SetView<DexType> dups =
-          Sets.intersection(customConversions.keySet(), wrapperConversions.keySet());
-      if (!dups.isEmpty()) {
-        throw reporter.fatalError(
-            new StringDiagnostic(
-                "Invalid desugared library configuration. "
-                    + "Duplicate types in custom conversions and wrapper conversions: "
-                    + String.join(
-                        ", ", dups.stream().map(DexType::toString).collect(Collectors.toSet())),
-                origin));
-      }
-    }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java
index 4aa99b6..16b0b9f 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java
@@ -145,7 +145,7 @@
     return rewritingFlags.isEmulatedInterfaceRewrittenType(type);
   }
 
-  public Map<DexType, WrapperDescriptor> getWrappers() {
+  public Map<DexType, List<DexMethod>> getWrappers() {
     return rewritingFlags.getWrappers();
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java
index 5ad734b..e125c53 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineRewritingFlags.java
@@ -10,12 +10,13 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.FieldAccessFlags;
 import com.android.tools.r8.graph.MethodAccessFlags;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import java.util.ArrayList;
 import java.util.IdentityHashMap;
-import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.function.Consumer;
@@ -38,7 +39,7 @@
       Map<DexMethod, DexMethod> emulatedVirtualRetargetThroughEmulatedInterface,
       Map<DexMethod, DexMethod[]> apiGenericTypesConversion,
       Map<DexType, EmulatedInterfaceDescriptor> emulatedInterfaces,
-      LinkedHashMap<DexType, WrapperDescriptor> wrappers,
+      Map<DexType, List<DexMethod>> wrappers,
       Map<DexType, DexType> legacyBackport,
       Set<DexType> dontRetarget,
       Map<DexType, CustomConversionDescriptor> customConversions,
@@ -100,8 +101,8 @@
   // Emulated interface descriptors.
   private final Map<DexType, EmulatedInterfaceDescriptor> emulatedInterfaces;
 
-  // Wrapper descriptors.
-  private final LinkedHashMap<DexType, WrapperDescriptor> wrappers;
+  // Wrappers and the list of methods they implement.
+  private final Map<DexType, List<DexMethod>> wrappers;
 
   private final Map<DexType, DexType> legacyBackport;
   private final Set<DexType> dontRetarget;
@@ -159,7 +160,7 @@
     return emulatedInterfaces;
   }
 
-  public Map<DexType, WrapperDescriptor> getWrappers() {
+  public Map<DexType, List<DexMethod>> getWrappers() {
     return wrappers;
   }
 
@@ -248,7 +249,7 @@
         ImmutableMap.builder();
     private final ImmutableMap.Builder<DexType, EmulatedInterfaceDescriptor> emulatedInterfaces =
         ImmutableMap.builder();
-    private final LinkedHashMap<DexType, WrapperDescriptor> wrappers = new LinkedHashMap<>();
+    private final ImmutableMap.Builder<DexType, List<DexMethod>> wrappers = ImmutableMap.builder();
     private final ImmutableMap.Builder<DexType, DexType> legacyBackport = ImmutableMap.builder();
     private final ImmutableSet.Builder<DexType> dontRetarget = ImmutableSet.builder();
     private final ImmutableMap.Builder<DexType, CustomConversionDescriptor> customConversions =
@@ -307,8 +308,8 @@
       apiGenericTypesConversion.put(method, conversions);
     }
 
-    public void addWrapper(DexType type, WrapperDescriptor descriptor) {
-      this.wrappers.put(type, descriptor);
+    public void addWrapper(DexType wrapperConversion, List<DexMethod> methods) {
+      wrappers.put(wrapperConversion, ImmutableList.copyOf(methods));
     }
 
     public void putLegacyBackport(DexType src, DexType target) {
@@ -366,7 +367,7 @@
           emulatedVirtualRetargetThroughEmulatedInterface.build(),
           apiGenericTypesConversion.build(),
           emulatedInterfaces.build(),
-          wrappers,
+          wrappers.build(),
           legacyBackport.build(),
           dontRetarget.build(),
           customConversions.build(),
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/WrapperDescriptor.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/WrapperDescriptor.java
deleted file mode 100644
index f4a158c..0000000
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/WrapperDescriptor.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// 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.ir.desugar.desugaredlibrary.machinespecification;
-
-import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexType;
-import java.util.List;
-
-public class WrapperDescriptor {
-  private final List<DexMethod> methods;
-  private final List<DexType> subwrappers;
-
-  public WrapperDescriptor(List<DexMethod> methods, List<DexType> directSubtypes) {
-    this.methods = methods;
-    this.subwrappers = directSubtypes;
-  }
-
-  public List<DexMethod> getMethods() {
-    return methods;
-  }
-
-  public List<DexType> getSubwrappers() {
-    return subwrappers;
-  }
-}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineWrapperConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineWrapperConverter.java
index a7ed82c..c0d9157 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineWrapperConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineWrapperConverter.java
@@ -12,19 +12,14 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.humanspecification.HumanRewritingFlags;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineRewritingFlags;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.WrapperDescriptor;
 import com.android.tools.r8.utils.MethodSignatureEquivalence;
 import com.google.common.base.Equivalence.Wrapper;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
 import java.util.ArrayList;
 import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import java.util.function.BiConsumer;
 
@@ -42,53 +37,6 @@
       HumanRewritingFlags rewritingFlags,
       MachineRewritingFlags.Builder builder,
       BiConsumer<String, Set<? extends DexReference>> warnConsumer) {
-    Map<DexType, WrapperDescriptorBuilder> descriptors = initializeDescriptors(rewritingFlags);
-    fillDescriptors(rewritingFlags, descriptors);
-    // The descriptors have to be ordered so that when processing a type, subtypes have been
-    // processed before.
-    LinkedHashMap<DexType, WrapperDescriptorBuilder> orderedDescriptors =
-        orderDescriptors(descriptors);
-    finalizeWrapperDescriptors(orderedDescriptors, builder);
-    warnConsumer.accept("The following types to wrap are missing: ", missingClasses);
-  }
-
-  private static class WrapperDescriptorBuilder {
-    private final List<DexMethod> methods = new ArrayList<>();
-    private final List<DexType> subwrappers = new ArrayList<>();
-
-    public WrapperDescriptorBuilder() {}
-
-    public List<DexMethod> getMethods() {
-      return methods;
-    }
-
-    public List<DexType> getSubwrappers() {
-      return subwrappers;
-    }
-
-    public void addSubwrapper(DexType type) {
-      subwrappers.add(type);
-    }
-
-    public WrapperDescriptor toWrapperDescriptor() {
-      methods.sort(DexMethod::compareTo);
-      subwrappers.sort(DexType::compareTo);
-      return new WrapperDescriptor(
-          ImmutableList.copyOf(methods), ImmutableList.copyOf(subwrappers));
-    }
-  }
-
-  private Map<DexType, WrapperDescriptorBuilder> initializeDescriptors(
-      HumanRewritingFlags rewritingFlags) {
-    Map<DexType, WrapperDescriptorBuilder> descriptors = new IdentityHashMap<>();
-    for (DexType wrapperType : rewritingFlags.getWrapperConversions().keySet()) {
-      descriptors.put(wrapperType, new WrapperDescriptorBuilder());
-    }
-    return descriptors;
-  }
-
-  private void fillDescriptors(
-      HumanRewritingFlags rewritingFlags, Map<DexType, WrapperDescriptorBuilder> descriptors) {
     rewritingFlags
         .getWrapperConversions()
         .forEach(
@@ -96,91 +44,53 @@
               DexClass wrapperClass = appInfo.definitionFor(wrapperType);
               if (wrapperClass == null) {
                 missingClasses.add(wrapperType);
-                descriptors.remove(wrapperType);
                 return;
               }
-              WrapperDescriptorBuilder descriptor = descriptors.get(wrapperType);
-              fillDescriptors(wrapperClass, excludedMethods, descriptor, descriptors);
+              List<DexMethod> methods;
+              if (wrapperClass.isEnum()) {
+                methods = ImmutableList.of();
+              } else {
+                methods = allImplementedMethods(wrapperClass, excludedMethods);
+                methods.sort(DexMethod::compareTo);
+              }
+              builder.addWrapper(wrapperType, methods);
             });
+    warnConsumer.accept("The following types to wrap are missing: ", missingClasses);
   }
 
-  private LinkedHashMap<DexType, WrapperDescriptorBuilder> orderDescriptors(
-      Map<DexType, WrapperDescriptorBuilder> descriptors) {
-    LinkedHashMap<DexType, WrapperDescriptorBuilder> orderedDescriptors = new LinkedHashMap<>();
-    List<DexType> preOrdered = new ArrayList<>(descriptors.keySet());
-    preOrdered.sort(DexType::compareTo);
-    LinkedList<DexType> workList = new LinkedList<>(preOrdered);
-    while (!workList.isEmpty()) {
-      DexType dexType = workList.removeFirst();
-      WrapperDescriptorBuilder descriptor = descriptors.get(dexType);
-      List<DexType> subwrappers = descriptor.getSubwrappers();
-      if (Iterables.all(subwrappers, orderedDescriptors::containsKey)) {
-        orderedDescriptors.put(dexType, descriptor);
-      } else {
-        workList.addLast(dexType);
-      }
-    }
-    return orderedDescriptors;
-  }
-
-  private void finalizeWrapperDescriptors(
-      LinkedHashMap<DexType, WrapperDescriptorBuilder> descriptors,
-      MachineRewritingFlags.Builder builder) {
-    descriptors.forEach(
-        (type, descriptor) -> {
-          LinkedList<DexType> workList = new LinkedList<>(descriptor.getSubwrappers());
-          while (!workList.isEmpty()) {
-            DexType dexType = workList.removeFirst();
-            List<DexType> subwrappers = descriptors.get(dexType).getSubwrappers();
-            descriptor.getSubwrappers().removeAll(subwrappers);
-            workList.addAll(subwrappers);
-          }
-          builder.addWrapper(type, descriptor.toWrapperDescriptor());
-        });
-  }
-
-  private void fillDescriptors(
-      DexClass wrapperClass,
-      Set<DexMethod> excludedMethods,
-      WrapperDescriptorBuilder descriptor,
-      Map<DexType, WrapperDescriptorBuilder> descriptors) {
+  private List<DexMethod> allImplementedMethods(
+      DexClass wrapperClass, Set<DexMethod> excludedMethods) {
     HashSet<Wrapper<DexMethod>> wrappers = new HashSet<>();
     for (DexMethod excludedMethod : excludedMethods) {
       wrappers.add(equivalence.wrap(excludedMethod));
     }
     LinkedList<DexClass> workList = new LinkedList<>();
-    List<DexMethod> implementedMethods = descriptor.getMethods();
+    List<DexMethod> implementedMethods = new ArrayList<>();
     workList.add(wrapperClass);
     while (!workList.isEmpty()) {
       DexClass dexClass = workList.removeFirst();
-      if (dexClass != wrapperClass && descriptors.containsKey(dexClass.type)) {
-        descriptors.get(dexClass.type).addSubwrapper(wrapperClass.type);
-      }
-      if (!wrapperClass.isEnum()) {
-        for (DexEncodedMethod virtualMethod : dexClass.virtualMethods()) {
-          if (!virtualMethod.isPrivateMethod()
-              // Don't include hashCode and equals overrides, as hashCode and equals are added to
-              // all wrappers regardless.
-              && (!appInfo.dexItemFactory().objectMembers.hashCode.match(virtualMethod))
-              && (!appInfo.dexItemFactory().objectMembers.equals.match(virtualMethod))) {
-            assert virtualMethod.isProtectedMethod() || virtualMethod.isPublicMethod();
-            boolean alreadyAdded =
-                wrappers.contains(equivalence.wrap(virtualMethod.getReference()));
-            // This looks quadratic but given the size of the collections met in practice for
-            // desugared libraries (Max ~15) it does not matter.
-            if (!alreadyAdded) {
-              for (DexMethod alreadyImplementedMethod : implementedMethods) {
-                if (alreadyImplementedMethod.match(virtualMethod.getReference())) {
-                  alreadyAdded = true;
-                  break;
-                }
+      for (DexEncodedMethod virtualMethod : dexClass.virtualMethods()) {
+        if (!virtualMethod.isPrivateMethod()
+            // Don't include hashCode and equals overrides, as hashCode and equals are added to
+            // all wrappers regardless.
+            && (!appInfo.dexItemFactory().objectMembers.hashCode.match(virtualMethod))
+            && (!appInfo.dexItemFactory().objectMembers.equals.match(virtualMethod))) {
+          assert virtualMethod.isProtectedMethod() || virtualMethod.isPublicMethod();
+          boolean alreadyAdded = wrappers.contains(equivalence.wrap(virtualMethod.getReference()));
+          // This looks quadratic but given the size of the collections met in practice for
+          // desugared libraries (Max ~15) it does not matter.
+          if (!alreadyAdded) {
+            for (DexMethod alreadyImplementedMethod : implementedMethods) {
+              if (alreadyImplementedMethod.match(virtualMethod.getReference())) {
+                alreadyAdded = true;
+                break;
               }
             }
-            if (!alreadyAdded) {
-              assert !virtualMethod.isFinal()
-                  : "Cannot wrap final method " + virtualMethod + " while wrapping " + wrapperClass;
-              implementedMethods.add(virtualMethod.getReference());
-            }
+          }
+          if (!alreadyAdded) {
+            assert !virtualMethod.isFinal()
+                : "Cannot wrap final method " + virtualMethod + " while wrapping " + wrapperClass;
+            implementedMethods.add(virtualMethod.getReference());
           }
         }
       }
@@ -197,5 +107,6 @@
         workList.add(superClass);
       }
     }
+    return implementedMethods;
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/apiconverter/NullableConversionCfCodeProvider.java b/src/main/java/com/android/tools/r8/ir/synthetic/apiconverter/NullableConversionCfCodeProvider.java
index 8f0f2f4..a32d51e 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/apiconverter/NullableConversionCfCodeProvider.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/apiconverter/NullableConversionCfCodeProvider.java
@@ -193,19 +193,14 @@
 
   public static class WrapperConversionCfCodeProvider extends NullableConversionCfCodeProvider {
 
-    private final DexField reverseWrapperField;
-    private final DexField wrapperField;
-    private final List<DexMethod> subwrapperConvertList;
+    DexField reverseWrapperField;
+    DexField wrapperField;
 
     public WrapperConversionCfCodeProvider(
-        AppView<?> appView,
-        DexField reverseWrapperField,
-        DexField wrapperField,
-        List<DexMethod> subwrapperConvertList) {
+        AppView<?> appView, DexField reverseWrapperField, DexField wrapperField) {
       super(appView, wrapperField.holder);
       this.reverseWrapperField = reverseWrapperField;
       this.wrapperField = wrapperField;
-      this.subwrapperConvertList = subwrapperConvertList;
     }
 
     @Override
@@ -233,23 +228,6 @@
       instructions.add(unwrapDest);
       instructions.add(frame.clone());
 
-      // if (arg instanceOf Subtype) {
-      //     return SubtypeWrapper.convert((Subtype) arg)
-      // };
-      for (DexMethod convert : subwrapperConvertList) {
-        CfLabel dest = new CfLabel();
-        DexType convertArgType = convert.getArgumentType(0, true);
-        instructions.add(new CfLoad(ValueType.fromDexType(argType), 0));
-        instructions.add(new CfInstanceOf(convertArgType));
-        instructions.add(new CfIf(If.Type.EQ, ValueType.INT, dest));
-        instructions.add(new CfLoad(ValueType.fromDexType(argType), 0));
-        instructions.add(new CfCheckCast(convertArgType));
-        instructions.add(new CfInvoke(Opcodes.INVOKESTATIC, convert, false));
-        instructions.add(new CfReturn(ValueType.fromDexType(reverseWrapperField.type)));
-        instructions.add(dest);
-        instructions.add(frame.clone());
-      }
-
       // return new Wrapper(wrappedValue);
       instructions.add(new CfNew(wrapperField.holder));
       instructions.add(CfStackInstruction.fromAsm(Opcodes.DUP));
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/UnwrapConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/UnwrapConversionTest.java
index a61445b..278ec26 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/UnwrapConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/UnwrapConversionTest.java
@@ -14,12 +14,9 @@
 import com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.StringUtils;
-import java.util.Arrays;
 import java.util.List;
 import java.util.function.DoubleConsumer;
 import java.util.function.IntConsumer;
-import java.util.stream.BaseStream;
-import java.util.stream.IntStream;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -33,7 +30,7 @@
   private final CompilationSpecification compilationSpecification;
 
   private static final AndroidApiLevel MIN_SUPPORTED = AndroidApiLevel.N;
-  private static final String EXPECTED_RESULT = StringUtils.lines("true", "true", "true", "true");
+  private static final String EXPECTED_RESULT = StringUtils.lines("true", "true");
 
   @Parameters(name = "{0}, spec: {1}, {2}")
   public static List<Object[]> data() {
@@ -67,22 +64,6 @@
 
     @SuppressWarnings("all")
     public static void main(String[] args) {
-      consumerTest();
-      streamTest();
-    }
-
-    private static void streamTest() {
-      // Type wrapper.
-      IntStream intStream = Arrays.stream(new int[] {1});
-      BaseStream<?, ?> unwrapped = CustomLibClass.identity(intStream);
-      System.out.println(unwrapped == intStream);
-
-      // Vivified wrapper.
-      IntStream consumer = CustomLibClass.getStream();
-      System.out.println(CustomLibClass.testStream(consumer));
-    }
-
-    private static void consumerTest() {
       // Type wrapper.
       IntConsumer intConsumer = i -> {};
       IntConsumer unwrappedIntConsumer = CustomLibClass.identity(intConsumer);
@@ -114,21 +95,5 @@
     public static boolean testConsumer(DoubleConsumer doubleConsumer) {
       return doubleConsumer == consumer;
     }
-
-    private static IntStream intStream = Arrays.stream(new int[] {0});
-
-    @SuppressWarnings("WeakerAccess")
-    public static BaseStream<Integer, IntStream> identity(IntStream arg) {
-      return arg;
-    }
-
-    public static IntStream getStream() {
-      return intStream;
-    }
-
-    @SuppressWarnings("WeakerAccess")
-    public static boolean testStream(BaseStream<?, ?> stream) {
-      return stream == intStream;
-    }
   }
 }
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/InputStreamTransferToTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/InputStreamTransferToTest.java
index 7721551..54c88bf 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/InputStreamTransferToTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/InputStreamTransferToTest.java
@@ -4,7 +4,7 @@
 
 package com.android.tools.r8.desugar.desugaredlibrary.jdk11;
 
-import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.SPECIFICATIONS_WITH_CF2CF;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.DEFAULT_SPECIFICATIONS;
 import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11_PATH;
 
 import com.android.tools.r8.TestParameters;
@@ -38,9 +38,9 @@
   @Parameters(name = "{0}, spec: {1}, {2}")
   public static List<Object[]> data() {
     return buildParameters(
-        getTestParameters().withAllRuntimesAndApiLevels().enableApiLevelsForCf().build(),
+        getTestParameters().withAllRuntimesAndApiLevels().build(),
         ImmutableList.of(JDK11_PATH),
-        SPECIFICATIONS_WITH_CF2CF);
+        DEFAULT_SPECIFICATIONS);
   }
 
   public InputStreamTransferToTest(