Update naming convention for desugared library synthetic types

Bug: 184026720
Change-Id: I94e5f685f85c077072dcd87d2ef2d678d6f32fb7
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/PrefixRewritingMapper.java b/src/main/java/com/android/tools/r8/ir/desugar/PrefixRewritingMapper.java
index eb4f662..f5861d7 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/PrefixRewritingMapper.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/PrefixRewritingMapper.java
@@ -11,9 +11,9 @@
 import com.android.tools.r8.graph.DexProto;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.legacyspecification.LegacyDesugaredLibrarySpecification;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
 import java.util.Map;
 import java.util.Set;
@@ -30,6 +30,8 @@
 
   public abstract DexType rewrittenType(DexType type, AppView<?> appView);
 
+  public abstract DexType rewrittenContextType(DexType type, AppView<?> appView);
+
   public boolean hasRewrittenType(DexType type, AppView<?> appView) {
     return rewrittenType(type, appView) != null;
   }
@@ -48,8 +50,6 @@
 
   public abstract boolean isRewriting();
 
-  public abstract boolean shouldRewriteTypeName(String typeName);
-
   public abstract void forAllRewrittenTypes(Consumer<DexType> consumer);
 
   public static class DesugarPrefixRewritingMapper extends PrefixRewritingMapper {
@@ -57,7 +57,6 @@
     private final Set<DexType> notRewritten = Sets.newConcurrentHashSet();
     private final Map<DexType, DexType> rewritten = new ConcurrentHashMap<>();
     private final Map<DexString, DexString> initialPrefixes;
-    private final Set<String> initialPrefixStrings;
     private final DexItemFactory factory;
     private final boolean l8Compilation;
 
@@ -67,13 +66,10 @@
       this.factory = itemFactory;
       this.l8Compilation = libraryCompilation;
       ImmutableMap.Builder<DexString, DexString> builder = ImmutableMap.builder();
-      ImmutableSet.Builder<String> prefixStringBuilder = ImmutableSet.builder();
       for (String key : prefixes.keySet()) {
-        prefixStringBuilder.add(key);
         builder.put(toDescriptorPrefix(key), toDescriptorPrefix(prefixes.get(key)));
       }
       this.initialPrefixes = builder.build();
-      this.initialPrefixStrings = prefixStringBuilder.build();
       validatePrefixes(prefixes);
     }
 
@@ -129,6 +125,36 @@
       return computePrefix(type, appView);
     }
 
+    @Override
+    public DexType rewrittenContextType(DexType type, AppView<?> appView) {
+      DexType rewritten = rewrittenType(type, appView);
+      if (rewritten != null) {
+        return rewritten;
+      }
+      LegacyDesugaredLibrarySpecification desugaredLibrarySpecification =
+          appView.options().desugaredLibrarySpecification;
+      if (desugaredLibrarySpecification.getEmulateLibraryInterface().containsKey(type)) {
+        return desugaredLibrarySpecification.getEmulateLibraryInterface().get(type);
+      }
+      for (Map<DexType, DexType> value :
+          desugaredLibrarySpecification.getRetargetCoreLibMember().values()) {
+        if (value.containsKey(type)) {
+          // Hack until machine specification are ready.
+          String prefix =
+              DescriptorUtils.getJavaTypeFromBinaryName(
+                  desugaredLibrarySpecification.getSynthesizedLibraryClassesPackagePrefix());
+          String interfaceType = type.toString();
+          int firstPackage = interfaceType.indexOf('.');
+          return appView
+              .dexItemFactory()
+              .createType(
+                  DescriptorUtils.javaTypeToDescriptor(
+                      prefix + interfaceType.substring(firstPackage + 1)));
+        }
+      }
+      return null;
+    }
+
     // Besides L8 compilation, program types should not be rewritten.
     private void failIfRewritingProgramType(DexType type, AppView<?> appView) {
       if (l8Compilation) {
@@ -192,17 +218,6 @@
     public boolean isRewriting() {
       return true;
     }
-
-    @Override
-    public boolean shouldRewriteTypeName(String typeName) {
-      // TODO(b/154800164): We could use tries instead of looking-up everywhere.
-      for (DexString prefix : initialPrefixes.keySet()) {
-        if (typeName.startsWith(prefix.toString())) {
-          return true;
-        }
-      }
-      return false;
-    }
   }
 
   public static class EmptyPrefixRewritingMapper extends PrefixRewritingMapper {
@@ -213,6 +228,11 @@
     }
 
     @Override
+    public DexType rewrittenContextType(DexType type, AppView<?> appView) {
+      return null;
+    }
+
+    @Override
     public void rewriteType(DexType type, DexType rewrittenType) {}
 
     @Override
@@ -221,11 +241,6 @@
     }
 
     @Override
-    public boolean shouldRewriteTypeName(String typeName) {
-      return false;
-    }
-
-    @Override
     public void forAllRewrittenTypes(Consumer<DexType> consumer) {}
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java
index 558faf7..987dc8d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java
@@ -235,6 +235,7 @@
             .dexItemFactory()
             .createSynthesizedType(
                 DescriptorUtils.javaTypeToDescriptor(VIVIFIED_PREFIX + type.toString()));
+    // We would need to ensure a classpath class for each type to remove this rewriteType call.
     appView.rewritePrefix.rewriteType(vivifiedType, type);
     return vivifiedType;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterSyntheticHelper.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterSyntheticHelper.java
index 8f7d25f..5519d95 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterSyntheticHelper.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterSyntheticHelper.java
@@ -19,7 +19,6 @@
 import com.android.tools.r8.ir.synthetic.EmulateDispatchSyntheticCfCodeProvider;
 import com.android.tools.r8.synthesis.SyntheticClassBuilder;
 import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
-import com.android.tools.r8.utils.DescriptorUtils;
 import java.util.LinkedHashMap;
 
 public class DesugaredLibraryRetargeterSyntheticHelper {
@@ -85,10 +84,7 @@
                   context,
                   appView,
                   classBuilder -> buildHolderDispatchMethod(classBuilder, itfClass, descriptor),
-                  clazz -> {
-                    eventConsumer.acceptDesugaredLibraryRetargeterDispatchClasspathClass(clazz);
-                    rewriteType(clazz.type);
-                  });
+                  eventConsumer::acceptDesugaredLibraryRetargeterDispatchClasspathClass);
     }
     DexMethod dispatchMethod =
         emulatedHolderDispatchMethod(syntheticClass.type, emulatedDispatchMethod);
@@ -112,10 +108,7 @@
             holderContext,
             appView,
             classBuilder -> buildHolderDispatchMethod(classBuilder, itfClass, descriptor),
-            clazz -> {
-              eventConsumer.acceptDesugaredLibraryRetargeterDispatchProgramClass(clazz);
-              rewriteType(clazz.type);
-            });
+            eventConsumer::acceptDesugaredLibraryRetargeterDispatchProgramClass);
   }
 
   public DexClass ensureEmulatedInterfaceDispatchMethod(
@@ -138,10 +131,7 @@
             context,
             appView,
             classBuilder -> buildInterfaceDispatchMethod(classBuilder, descriptor),
-            clazz -> {
-              eventConsumer.acceptDesugaredLibraryRetargeterDispatchClasspathClass(clazz);
-              rewriteType(clazz.type);
-            });
+            eventConsumer::acceptDesugaredLibraryRetargeterDispatchClasspathClass);
   }
 
   public DexClass ensureEmulatedInterfaceDispatchMethod(
@@ -158,10 +148,7 @@
             itfContext,
             appView,
             classBuilder -> buildInterfaceDispatchMethod(classBuilder, descriptor),
-            clazz -> {
-              eventConsumer.acceptDesugaredLibraryRetargeterDispatchProgramClass(clazz);
-              rewriteType(clazz.type);
-            });
+            eventConsumer::acceptDesugaredLibraryRetargeterDispatchProgramClass);
   }
 
   private void buildInterfaceDispatchMethod(
@@ -216,12 +203,4 @@
             methodSig.getHolderType(), forwardingMethod, itfMethod, new LinkedHashMap<>(), appView)
         .generateCfCode();
   }
-
-  private void rewriteType(DexType type) {
-    String newName =
-        appView.options().desugaredLibrarySpecification.convertJavaNameToDesugaredLibrary(type);
-    DexType newType =
-        appView.dexItemFactory().createType(DescriptorUtils.javaTypeToDescriptor(newName));
-    appView.rewritePrefix.rewriteType(type, newType);
-  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
index a40d69a..d30f717 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
@@ -43,7 +43,6 @@
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.position.MethodPosition;
 import com.android.tools.r8.synthesis.SyntheticNaming;
-import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.collections.ProgramMethodSet;
 import com.android.tools.r8.utils.structural.Ordered;
@@ -160,8 +159,6 @@
     Map<DexType, DexType> emulateLibraryInterface =
         options.desugaredLibrarySpecification.getEmulateLibraryInterface();
     for (DexType interfaceType : emulateLibraryInterface.keySet()) {
-      addRewriteRulesForEmulatedInterface(
-          interfaceType, emulateLibraryInterface.get(interfaceType).toSourceString());
       DexClass emulatedInterfaceClass = appView.definitionFor(interfaceType);
       if (emulatedInterfaceClass != null) {
         for (DexEncodedMethod encodedMethod :
@@ -172,35 +169,6 @@
     }
   }
 
-  void addRewriteRulesForEmulatedInterface(
-      DexType emulatedInterface, String rewrittenEmulatedInterface) {
-    addCompanionClassRewriteRule(emulatedInterface, rewrittenEmulatedInterface);
-    appView.rewritePrefix.rewriteType(
-        InterfaceDesugaringSyntheticHelper.getEmulateLibraryInterfaceClassType(
-            emulatedInterface, factory),
-        factory.createType(
-            DescriptorUtils.javaTypeToDescriptor(
-                rewrittenEmulatedInterface
-                    + InterfaceDesugaringSyntheticHelper.EMULATE_LIBRARY_CLASS_NAME_SUFFIX)));
-  }
-
-  private void addCompanionClassRewriteRule(DexType interfaceType, String rewrittenType) {
-    addCompanionClassRewriteRule(interfaceType, rewrittenType, appView);
-  }
-
-  static void addCompanionClassRewriteRule(
-      DexType interfaceType, String rewrittenType, AppView<?> appView) {
-    appView.rewritePrefix.rewriteType(
-        InterfaceDesugaringSyntheticHelper.getCompanionClassType(
-            interfaceType, appView.dexItemFactory()),
-        appView
-            .dexItemFactory()
-            .createType(
-                DescriptorUtils.javaTypeToDescriptor(
-                    rewrittenType
-                        + InterfaceDesugaringSyntheticHelper.COMPANION_CLASS_NAME_SUFFIX)));
-  }
-
   private boolean isAlreadyDesugared(CfInvoke invoke, ProgramMethod context) {
     return Iterables.any(
         precedingDesugarings, desugaring -> desugaring.needsDesugaring(invoke, context));
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
index a29bfcf..10e3e32 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
@@ -16,7 +16,6 @@
 import com.android.tools.r8.graph.DexClassAndMethod;
 import com.android.tools.r8.graph.DexClasspathClass;
 import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexLibraryClass;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProgramClass;
@@ -419,13 +418,15 @@
 
   // Addition and creation of synthetic items.
 
-  private DexProgramClass internalEnsureDexProgramClass(
+  private DexProgramClass internalEnsureFixedProgramClass(
       SyntheticKind kind,
       Consumer<SyntheticProgramClassBuilder> classConsumer,
       Consumer<DexProgramClass> onCreationConsumer,
       SynthesizingContext outerContext,
-      DexType type,
       AppView<?> appView) {
+    Function<SynthesizingContext, DexType> contextToType =
+        c -> SyntheticNaming.createFixedType(kind, c, appView.dexItemFactory());
+    DexType type = contextToType.apply(outerContext);
     // Fast path is that the synthetic is already present. If so it must be a program class.
     DexClass dexClass = appView.definitionFor(type);
     if (dexClass != null) {
@@ -452,7 +453,8 @@
               },
               outerContext,
               type,
-              appView.dexItemFactory());
+              contextToType,
+              appView);
       onCreationConsumer.accept(dexProgramClass);
       return dexProgramClass;
     }
@@ -463,15 +465,33 @@
       Consumer<SyntheticProgramClassBuilder> fn,
       SynthesizingContext outerContext,
       DexType type,
-      DexItemFactory factory) {
+      Function<SynthesizingContext, DexType> contextToType,
+      AppView<?> appView) {
+    registerSyntheticTypeRewriting(outerContext, contextToType, appView, type);
     SyntheticProgramClassBuilder classBuilder =
-        new SyntheticProgramClassBuilder(type, kind, outerContext, factory);
+        new SyntheticProgramClassBuilder(type, kind, outerContext, appView.dexItemFactory());
     fn.accept(classBuilder);
     DexProgramClass clazz = classBuilder.build();
     addPendingDefinition(new SyntheticProgramClassDefinition(kind, outerContext, clazz));
     return clazz;
   }
 
+  private void registerSyntheticTypeRewriting(
+      SynthesizingContext outerContext,
+      Function<SynthesizingContext, DexType> contextToType,
+      AppView<?> appView,
+      DexType type) {
+    DexType rewrittenContextType =
+        appView.rewritePrefix.rewrittenContextType(
+            outerContext.getSynthesizingContextType(), appView);
+    if (rewrittenContextType == null) {
+      return;
+    }
+    SynthesizingContext synthesizingContext = SynthesizingContext.fromType(rewrittenContextType);
+    DexType rewrittenType = contextToType.apply(synthesizingContext);
+    appView.rewritePrefix.rewriteType(type, rewrittenType);
+  }
+
   public DexProgramClass createClass(
       SyntheticKind kind,
       UniqueContext context,
@@ -480,10 +500,12 @@
     // Obtain the outer synthesizing context in the case the context itself is synthetic.
     // This is to ensure a flat input-type -> synthetic-item mapping.
     SynthesizingContext outerContext = getSynthesizingContext(context.getClassContext(), appView);
-    DexType type =
-        SyntheticNaming.createInternalType(
-            kind, outerContext, context.getSyntheticSuffix(), appView.dexItemFactory());
-    return internalCreateProgramClass(kind, fn, outerContext, type, appView.dexItemFactory());
+    Function<SynthesizingContext, DexType> contextToType =
+        c ->
+            SyntheticNaming.createInternalType(
+                kind, c, context.getSyntheticSuffix(), appView.dexItemFactory());
+    return internalCreateProgramClass(
+        kind, fn, outerContext, contextToType.apply(outerContext), contextToType, appView);
   }
 
   // TODO(b/172194101): Make this take a unique context.
@@ -493,8 +515,10 @@
       AppView<?> appView,
       Consumer<SyntheticProgramClassBuilder> fn) {
     SynthesizingContext outerContext = internalGetOuterContext(context, appView);
-    DexType type = SyntheticNaming.createFixedType(kind, outerContext, appView.dexItemFactory());
-    return internalCreateProgramClass(kind, fn, outerContext, type, appView.dexItemFactory());
+    Function<SynthesizingContext, DexType> contextToType =
+        c -> SyntheticNaming.createFixedType(kind, c, appView.dexItemFactory());
+    return internalCreateProgramClass(
+        kind, fn, outerContext, contextToType.apply(outerContext), contextToType, appView);
   }
 
   public DexProgramClass getExistingFixedClass(
@@ -530,8 +554,7 @@
       Consumer<DexProgramClass> onCreationConsumer) {
     assert kind.isFixedSuffixSynthetic;
     SynthesizingContext outerContext = internalGetOuterContext(context, appView);
-    DexType type = SyntheticNaming.createFixedType(kind, outerContext, appView.dexItemFactory());
-    return internalEnsureDexProgramClass(kind, fn, onCreationConsumer, outerContext, type, appView);
+    return internalEnsureFixedProgramClass(kind, fn, onCreationConsumer, outerContext, appView);
   }
 
   public ProgramMethod ensureFixedClassMethod(
@@ -589,13 +612,15 @@
                 + " class.");
   }
 
-  private DexClasspathClass internalEnsureDexClasspathClass(
+  private DexClasspathClass internalEnsureFixedClasspathClass(
       SyntheticKind kind,
       Consumer<SyntheticClasspathClassBuilder> classConsumer,
       Consumer<DexClasspathClass> onCreationConsumer,
       SynthesizingContext outerContext,
-      DexType type,
       AppView<?> appView) {
+    Function<SynthesizingContext, DexType> contextToType =
+        (c) -> SyntheticNaming.createFixedType(kind, c, appView.dexItemFactory());
+    DexType type = contextToType.apply(outerContext);
     synchronized (type) {
       DexClass clazz = appView.definitionFor(type);
       if (clazz != null) {
@@ -604,6 +629,7 @@
         }
         return clazz.asClasspathClass();
       }
+      registerSyntheticTypeRewriting(outerContext, contextToType, appView, type);
       SyntheticClasspathClassBuilder classBuilder =
           new SyntheticClasspathClassBuilder(type, kind, outerContext, appView.dexItemFactory());
       classConsumer.accept(classBuilder);
@@ -620,9 +646,8 @@
       AppView<?> appView,
       Consumer<SyntheticClasspathClassBuilder> classConsumer) {
     SynthesizingContext outerContext = SynthesizingContext.fromType(contextType);
-    DexType type = SyntheticNaming.createFixedType(kind, outerContext, appView.dexItemFactory());
-    return internalEnsureDexClasspathClass(
-        kind, classConsumer, ignored -> {}, outerContext, type, appView);
+    return internalEnsureFixedClasspathClass(
+        kind, classConsumer, ignored -> {}, outerContext, appView);
   }
 
   public DexClasspathClass ensureFixedClasspathClass(
@@ -634,9 +659,8 @@
     // Obtain the outer synthesizing context in the case the context itself is synthetic.
     // This is to ensure a flat input-type -> synthetic-item mapping.
     SynthesizingContext outerContext = SynthesizingContext.fromNonSyntheticInputContext(context);
-    DexType type = SyntheticNaming.createFixedType(kind, outerContext, appView.dexItemFactory());
-    return internalEnsureDexClasspathClass(
-        kind, classConsumer, onCreationConsumer, outerContext, type, appView);
+    return internalEnsureFixedClasspathClass(
+        kind, classConsumer, onCreationConsumer, outerContext, appView);
   }
 
   public DexClassAndMethod ensureFixedClasspathClassMethod(
@@ -703,8 +727,7 @@
     // Obtain the outer synthesizing context in the case the context itself is synthetic.
     // This is to ensure a flat input-type -> synthetic-item mapping.
     SynthesizingContext outerContext = SynthesizingContext.fromType(contextType);
-    DexType type = SyntheticNaming.createFixedType(kind, outerContext, appView.dexItemFactory());
-    return internalEnsureDexProgramClass(kind, fn, onCreationConsumer, outerContext, type, appView);
+    return internalEnsureFixedProgramClass(kind, fn, onCreationConsumer, outerContext, appView);
   }
 
   /** Create a single synthetic method item. */