Fix DesugarDescription for DesugaredLibraryRetargeter

Bug: b/270144318
Change-Id: I3e1981c757b5921c44583a04dc12cac829bb527e
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java
index 11f9c1b..fd30618 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java
@@ -4,8 +4,6 @@
 
 package com.android.tools.r8.ir.desugar.desugaredlibrary.retargeter;
 
-import static com.android.tools.r8.ir.desugar.desugaredlibrary.retargeter.DesugaredLibraryRetargeter.InvokeRetargetingResult.NO_REWRITING;
-
 import com.android.tools.r8.cf.code.CfFieldInstruction;
 import com.android.tools.r8.cf.code.CfInstruction;
 import com.android.tools.r8.cf.code.CfInvoke;
@@ -15,21 +13,15 @@
 import com.android.tools.r8.graph.DexClassAndMethod;
 import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.MethodResolutionResult;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.desugar.CfInstructionDesugaring;
-import com.android.tools.r8.ir.desugar.CfInstructionDesugaringCollection;
 import com.android.tools.r8.ir.desugar.CfInstructionDesugaringEventConsumer;
-import com.android.tools.r8.ir.desugar.FreshLocalProvider;
-import com.android.tools.r8.ir.desugar.LocalStackAllocator;
+import com.android.tools.r8.ir.desugar.DesugarDescription;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.EmulatedDispatchMethodDescriptor;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
-import com.android.tools.r8.ir.desugar.desugaredlibrary.retargeter.DesugaredLibraryRetargeterSynthesizerEventConsumer.DesugaredLibraryRetargeterInstructionEventConsumer;
-import java.util.Collection;
 import java.util.Collections;
-import java.util.List;
 import java.util.Map;
 import java.util.function.BiFunction;
 import java.util.function.Consumer;
@@ -66,53 +58,89 @@
   }
 
   @Override
-  public Collection<CfInstruction> desugarInstruction(
-      CfInstruction instruction,
-      FreshLocalProvider freshLocalProvider,
-      LocalStackAllocator localStackAllocator,
-      CfInstructionDesugaringEventConsumer eventConsumer,
-      ProgramMethod context,
-      MethodProcessingContext methodProcessingContext,
-      CfInstructionDesugaringCollection desugaringCollection,
-      DexItemFactory dexItemFactory) {
-    if (instruction.isStaticFieldGet() && needsDesugaring(instruction, context)) {
-      return desugarFieldInstruction(instruction.asFieldInstruction(), context);
-    } else if (instruction.isInvoke() && needsDesugaring(instruction, context)) {
-      return desugarInvoke(instruction.asInvoke(), eventConsumer, context, methodProcessingContext);
-    }
-    return null;
-  }
-
-  private Collection<CfInstruction> desugarFieldInstruction(
-      CfFieldInstruction fieldInstruction, ProgramMethod context) {
-    DexField fieldRetarget = fieldRetarget(fieldInstruction, context);
-    assert fieldRetarget != null;
-    assert fieldInstruction.isStaticFieldGet();
-    return Collections.singletonList(fieldInstruction.createWithField(fieldRetarget));
-  }
-
-  private List<CfInstruction> desugarInvoke(
-      CfInvoke invoke,
-      CfInstructionDesugaringEventConsumer eventConsumer,
-      ProgramMethod context,
-      MethodProcessingContext methodProcessingContext) {
-    InvokeRetargetingResult invokeRetargetingResult = computeNewInvokeTarget(invoke, context);
-    assert invokeRetargetingResult.hasNewInvokeTarget();
-    DexMethod newInvokeTarget =
-        invokeRetargetingResult.getNewInvokeTarget(eventConsumer, methodProcessingContext);
-    assert appView.definitionFor(newInvokeTarget.getHolderType()) != null;
-    assert !appView.definitionFor(newInvokeTarget.getHolderType()).isInterface();
-    return Collections.singletonList(new CfInvoke(Opcodes.INVOKESTATIC, newInvokeTarget, false));
-  }
-
-  @Override
-  public boolean needsDesugaring(CfInstruction instruction, ProgramMethod context) {
+  public DesugarDescription compute(CfInstruction instruction, ProgramMethod context) {
     if (instruction.isStaticFieldGet()) {
-      return fieldRetarget(instruction.asFieldInstruction(), context) != null;
-    } else if (instruction.isInvoke()) {
-      return computeNewInvokeTarget(instruction.asInvoke(), context).hasNewInvokeTarget();
+      return computeStaticFieldGetDescription(instruction, context);
     }
-    return false;
+    if (instruction.isInvoke()) {
+      return computeInvokeDescription(instruction, context);
+    }
+    return DesugarDescription.nothing();
+  }
+
+  private DesugarDescription computeInvokeDescription(
+      CfInstruction instruction, ProgramMethod context) {
+    if (appView.dexItemFactory().multiDexTypes.contains(context.getContextType())) {
+      return DesugarDescription.nothing();
+    }
+    CfInvoke cfInvoke = instruction.asInvoke();
+    DexMethod invokedMethod = cfInvoke.getMethod();
+    AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
+    MethodResolutionResult resolutionResult =
+        appInfo.resolveMethodLegacy(invokedMethod, cfInvoke.isInterface());
+    if (!resolutionResult.isSingleResolution()) {
+      return DesugarDescription.nothing();
+    }
+    assert resolutionResult.getSingleTarget() != null;
+    DexMethod singleTarget = resolutionResult.getSingleTarget().getReference();
+    if (cfInvoke.isInvokeStatic()) {
+      DexMethod retarget = staticRetarget.get(singleTarget);
+      return ensureInvokeRetargetingResult(retarget);
+    }
+    DesugarDescription retarget = computeNonStaticRetarget(singleTarget, false);
+    if (!retarget.needsDesugaring()) {
+      return DesugarDescription.nothing();
+    }
+    if (cfInvoke.isInvokeSuper(context.getHolderType())) {
+      DexClassAndMethod superTarget = appInfo.lookupSuperTarget(invokedMethod, context);
+      if (superTarget != null) {
+        assert !superTarget.getDefinition().isStatic();
+        return computeNonStaticRetarget(superTarget.getReference(), true);
+      }
+    }
+    return retarget;
+  }
+
+  private DesugarDescription createWithTarget(
+      BiFunction<CfInstructionDesugaringEventConsumer, MethodProcessingContext, DexMethod>
+          methodProvider) {
+    return DesugarDescription.builder()
+        .setDesugarRewrite(
+            (freshLocalProvider,
+                localStackAllocator,
+                eventConsumer,
+                context,
+                methodProcessingContext,
+                desugarings,
+                dexItemFactory) -> {
+              DexMethod newInvokeTarget =
+                  methodProvider.apply(eventConsumer, methodProcessingContext);
+              assert appView.definitionFor(newInvokeTarget.getHolderType()) != null;
+              assert !appView.definitionFor(newInvokeTarget.getHolderType()).isInterface();
+              return Collections.singletonList(
+                  new CfInvoke(Opcodes.INVOKESTATIC, newInvokeTarget, false));
+            })
+        .build();
+  }
+
+  private DesugarDescription computeStaticFieldGetDescription(
+      CfInstruction instruction, ProgramMethod context) {
+    CfFieldInstruction fieldInstruction = instruction.asFieldInstruction();
+    DexField fieldRetarget = fieldRetarget(fieldInstruction, context);
+    if (fieldRetarget == null) {
+      return DesugarDescription.nothing();
+    }
+    return DesugarDescription.builder()
+        .setDesugarRewrite(
+            (freshLocalProvider,
+                localStackAllocator,
+                eventConsumer,
+                context1,
+                methodProcessingContext,
+                desugarings,
+                dexItemFactory) ->
+                Collections.singletonList(fieldInstruction.createWithField(fieldRetarget)))
+        .build();
   }
 
   private DexField fieldRetarget(CfFieldInstruction fieldInstruction, ProgramMethod context) {
@@ -129,98 +157,26 @@
     return null;
   }
 
-  InvokeRetargetingResult ensureInvokeRetargetingResult(DexMethod retarget) {
+  DesugarDescription ensureInvokeRetargetingResult(DexMethod retarget) {
     if (retarget == null) {
-      return NO_REWRITING;
+      return DesugarDescription.nothing();
     }
-    return new InvokeRetargetingResult(
-        true,
-        (eventConsumer, methodProcessingContext) -> {
-          syntheticHelper.ensureRetargetMethod(retarget, eventConsumer);
-          return retarget;
-        });
+    return createWithTarget(
+        (eventConsumer, methodProcessingContext) ->
+            syntheticHelper.ensureRetargetMethod(retarget, eventConsumer));
   }
 
-  static class InvokeRetargetingResult {
-
-    static InvokeRetargetingResult NO_REWRITING =
-        new InvokeRetargetingResult(false, (ignored, alsoIgnored) -> null);
-
-    private final boolean hasNewInvokeTarget;
-    private final BiFunction<
-            DesugaredLibraryRetargeterInstructionEventConsumer, MethodProcessingContext, DexMethod>
-        newInvokeTargetSupplier;
-
-    private InvokeRetargetingResult(
-        boolean hasNewInvokeTarget,
-        BiFunction<
-                DesugaredLibraryRetargeterInstructionEventConsumer,
-                MethodProcessingContext,
-                DexMethod>
-            newInvokeTargetSupplier) {
-      this.hasNewInvokeTarget = hasNewInvokeTarget;
-      this.newInvokeTargetSupplier = newInvokeTargetSupplier;
-    }
-
-    public boolean hasNewInvokeTarget() {
-      return hasNewInvokeTarget;
-    }
-
-    public DexMethod getNewInvokeTarget(
-        DesugaredLibraryRetargeterInstructionEventConsumer eventConsumer,
-        MethodProcessingContext methodProcessingContext) {
-      assert hasNewInvokeTarget();
-      return newInvokeTargetSupplier.apply(eventConsumer, methodProcessingContext);
-    }
-  }
-
-  private InvokeRetargetingResult computeNewInvokeTarget(
-      CfInvoke instruction, ProgramMethod context) {
-    if (appView.dexItemFactory().multiDexTypes.contains(context.getContextType())) {
-      return NO_REWRITING;
-    }
-    CfInvoke cfInvoke = instruction.asInvoke();
-    DexMethod invokedMethod = cfInvoke.getMethod();
-    AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
-    MethodResolutionResult resolutionResult =
-        appInfo.resolveMethodLegacy(invokedMethod, cfInvoke.isInterface());
-    if (!resolutionResult.isSingleResolution()) {
-      return NO_REWRITING;
-    }
-    assert resolutionResult.getSingleTarget() != null;
-    DexMethod singleTarget = resolutionResult.getSingleTarget().getReference();
-    if (cfInvoke.isInvokeStatic()) {
-      DexMethod retarget = staticRetarget.get(singleTarget);
-      return retarget == null ? NO_REWRITING : ensureInvokeRetargetingResult(retarget);
-    }
-    InvokeRetargetingResult retarget = computeNonStaticRetarget(singleTarget, false);
-    if (!retarget.hasNewInvokeTarget()) {
-      return NO_REWRITING;
-    }
-    if (cfInvoke.isInvokeSuper(context.getHolderType())) {
-      DexClassAndMethod superTarget = appInfo.lookupSuperTarget(invokedMethod, context);
-      if (superTarget != null) {
-        assert !superTarget.getDefinition().isStatic();
-        return computeNonStaticRetarget(superTarget.getReference(), true);
-      }
-    }
-    return retarget;
-  }
-
-  private InvokeRetargetingResult computeNonStaticRetarget(
-      DexMethod singleTarget, boolean superInvoke) {
+  private DesugarDescription computeNonStaticRetarget(DexMethod singleTarget, boolean superInvoke) {
     EmulatedDispatchMethodDescriptor descriptor = emulatedVirtualRetarget.get(singleTarget);
     if (descriptor != null) {
-      return new InvokeRetargetingResult(
-          true,
+      return createWithTarget(
           (eventConsumer, methodProcessingContext) ->
               superInvoke
                   ? syntheticHelper.ensureForwardingMethod(descriptor, eventConsumer)
                   : syntheticHelper.ensureEmulatedHolderDispatchMethod(descriptor, eventConsumer));
     }
     if (covariantRetarget.containsKey(singleTarget)) {
-      return new InvokeRetargetingResult(
-          true,
+      return createWithTarget(
           (eventConsumer, methodProcessingContext) ->
               syntheticHelper.ensureCovariantRetargetMethod(
                   singleTarget,