Pass desugared classes directly to R8 in R8 partial

Bug: b/389575762
Change-Id: Ib399005edbd42926974b96d9e9a3df9b1fe1fa2c
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index 22492d9..ab2ef1b 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -357,8 +357,8 @@
     InternalOptions options = appView.options();
     R8PartialSubCompilationConfiguration subCompilationConfiguration =
         options.partialSubCompilationConfiguration;
-    if (subCompilationConfiguration != null
-        && subCompilationConfiguration.writeApplication(appView.appInfo().classes(), options)) {
+    if (subCompilationConfiguration != null) {
+      subCompilationConfiguration.writeApplication(appView.appInfo().classes(), options);
       return;
     }
     if (options.isGeneratingClassFiles()) {
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index ce41b05..03917cd 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -21,6 +21,7 @@
 import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppServices;
 import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexApplicationReadFlags;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedMethod;
@@ -300,6 +301,13 @@
         keepDeclarations = lazyLoaded.getKeepDeclarations();
         timing.begin("To direct app");
         DirectMappedDexApplication application = lazyLoaded.toDirect();
+        if (options.partialSubCompilationConfiguration != null) {
+          application =
+              options
+                  .partialSubCompilationConfiguration
+                  .asR8SubCompilationConfiguration()
+                  .commitDesugaringOutputClasses(application);
+        }
         timing.end();
         timing.end();
         options.loadMachineDesugaredLibrarySpecification(timing, application);
@@ -822,14 +830,7 @@
       // Validity checks.
       assert getDirectApp(appView).verifyCodeObjectsOwners();
       assert appView.appInfo().classes().stream().allMatch(clazz -> clazz.isValid(options));
-
-      assert options.testing.disableMappingToOriginalProgramVerification
-          || appView
-              .graphLens()
-              .verifyMappingToOriginalProgram(
-                  appView,
-                  new ApplicationReader(inputApp.withoutMainDexList(), options, timing)
-                      .readWithoutDumping(executorService));
+      assert verifyMappingToOriginalProgram(appView, inputApp, executorService);
 
       // Report synthetic rules (only for testing).
       // TODO(b/120959039): Move this to being reported through the graph consumer.
@@ -923,6 +924,25 @@
     timing.end();
   }
 
+  private boolean verifyMappingToOriginalProgram(
+      AppView<AppInfoWithClassHierarchy> appView,
+      AndroidApp inputAndroidApp,
+      ExecutorService executorService)
+      throws IOException {
+    if (options.testing.disableMappingToOriginalProgramVerification) {
+      return true;
+    }
+    if (options.partialSubCompilationConfiguration != null) {
+      // TODO(b/390587690): Find a way to re-enable this assert in R8 partial.
+      return true;
+    }
+    DexApplication inputApp =
+        new ApplicationReader(inputAndroidApp.withoutMainDexList(), options, timing)
+            .readWithoutDumping(executorService);
+    assert appView.graphLens().verifyMappingToOriginalProgram(appView, inputApp);
+    return true;
+  }
+
   private void writeKeepDeclarationsToConfigurationConsumer(
       List<KeepDeclaration> keepDeclarations) {
     if (options.configurationConsumer == null) {
diff --git a/src/main/java/com/android/tools/r8/R8Partial.java b/src/main/java/com/android/tools/r8/R8Partial.java
index 4c6de4e..bb44f32 100644
--- a/src/main/java/com/android/tools/r8/R8Partial.java
+++ b/src/main/java/com/android/tools/r8/R8Partial.java
@@ -161,11 +161,11 @@
     }
     InternalOptions d8Options = d8Command.getInternalOptions();
     options.partialCompilationConfiguration.d8DexOptionsConsumer.accept(d8Options);
-    R8PartialD8DexSubCompilationConfiguration partialSubCompilationConfiguration =
+    R8PartialD8DexSubCompilationConfiguration subCompilationConfiguration =
         new R8PartialD8DexSubCompilationConfiguration(timing);
-    d8Options.partialSubCompilationConfiguration = partialSubCompilationConfiguration;
+    d8Options.partialSubCompilationConfiguration = subCompilationConfiguration;
     D8.runInternal(d8App, d8Options, executor);
-    return new R8PartialD8DexResult(partialSubCompilationConfiguration.getOutputClasses());
+    return new R8PartialD8DexResult(subCompilationConfiguration.getOutputClasses());
   }
 
   private R8PartialDesugarResult runDesugarStep(R8PartialInput input, ExecutorService executor)
@@ -176,9 +176,8 @@
     //  As a simple example, it should be safe to postpone backporting to the R8 compilation.
     // TODO(b/389039057): This runs a full D8 compilation. For build speed, consider if the various
     //  passes in D8 can be disabled when the `partialSubCompilationConfiguration` is set.
-    Path desugarOutput = resolveTmp("desugar-output.zip");
     D8Command.Builder d8Builder =
-        D8Command.builder(options.reporter).setOutput(desugarOutput, OutputMode.ClassFile);
+        D8Command.builder(options.reporter).setProgramConsumer(ClassFileConsumer.emptyConsumer());
     // TODO(b/390327883): This should enable intermediate mode.
     input.configureDesugar(d8Builder);
     d8Builder.validate();
@@ -186,10 +185,11 @@
     AndroidApp d8App = d8Command.getInputApp();
     InternalOptions d8Options = d8Command.getInternalOptions();
     options.partialCompilationConfiguration.d8DesugarOptionsConsumer.accept(d8Options);
-    d8Options.partialSubCompilationConfiguration =
+    R8PartialD8DesugarSubCompilationConfiguration subCompilationConfiguration =
         new R8PartialD8DesugarSubCompilationConfiguration(timing);
+    d8Options.partialSubCompilationConfiguration = subCompilationConfiguration;
     D8.runInternal(d8App, d8Options, executor);
-    return new R8PartialDesugarResult(desugarOutput);
+    return new R8PartialDesugarResult(subCompilationConfiguration.getOutputClasses());
   }
 
   private void runR8PartialStep(
@@ -214,7 +214,6 @@
     // TODO(b/390389764): Disable desugaring.
     R8Command.Builder r8Builder =
         R8Command.builder(r8DiagnosticsHandler)
-            .addProgramFiles(desugarResult.getOutputPath())
             .enableLegacyFullModeForKeepRules(true)
             .setProgramConsumer(options.programConsumer);
     input.configure(r8Builder);
@@ -227,7 +226,8 @@
     InternalOptions r8Options = r8Command.getInternalOptions();
     options.partialCompilationConfiguration.r8OptionsConsumer.accept(r8Options);
     r8Options.partialSubCompilationConfiguration =
-        new R8PartialR8SubCompilationConfiguration(dexingResult.getOutputClasses(), timing);
+        new R8PartialR8SubCompilationConfiguration(
+            desugarResult.getOutputClasses(), dexingResult.getOutputClasses(), timing);
     r8Options.mapConsumer = options.mapConsumer;
     if (options.androidResourceProvider != null) {
       r8Options.androidResourceProvider = options.androidResourceProvider;
diff --git a/src/main/java/com/android/tools/r8/partial/R8PartialDesugarResult.java b/src/main/java/com/android/tools/r8/partial/R8PartialDesugarResult.java
index 6885303..37bae17 100644
--- a/src/main/java/com/android/tools/r8/partial/R8PartialDesugarResult.java
+++ b/src/main/java/com/android/tools/r8/partial/R8PartialDesugarResult.java
@@ -3,17 +3,18 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.partial;
 
-import java.nio.file.Path;
+import com.android.tools.r8.graph.DexProgramClass;
+import java.util.Collection;
 
 public class R8PartialDesugarResult {
 
-  private final Path outputPath;
+  private final Collection<DexProgramClass> outputClasses;
 
-  public R8PartialDesugarResult(Path outputPath) {
-    this.outputPath = outputPath;
+  public R8PartialDesugarResult(Collection<DexProgramClass> outputClasses) {
+    this.outputClasses = outputClasses;
   }
 
-  public Path getOutputPath() {
-    return outputPath;
+  public Collection<DexProgramClass> getOutputClasses() {
+    return outputClasses;
   }
 }
diff --git a/src/main/java/com/android/tools/r8/partial/R8PartialSubCompilationConfiguration.java b/src/main/java/com/android/tools/r8/partial/R8PartialSubCompilationConfiguration.java
index 08eb55d..0906f8a 100644
--- a/src/main/java/com/android/tools/r8/partial/R8PartialSubCompilationConfiguration.java
+++ b/src/main/java/com/android/tools/r8/partial/R8PartialSubCompilationConfiguration.java
@@ -33,9 +33,8 @@
   }
 
   /** Returns true if normal writing should be aborted. */
-  public boolean writeApplication(
-      Collection<DexProgramClass> outputClasses, InternalOptions options) {
-    return false;
+  public void writeApplication(Collection<DexProgramClass> outputClasses, InternalOptions options) {
+    assert false;
   }
 
   public static class R8PartialD8DexSubCompilationConfiguration
@@ -58,29 +57,45 @@
     }
 
     @Override
-    public boolean writeApplication(
+    public void writeApplication(
         Collection<DexProgramClass> outputClasses, InternalOptions options) {
       this.outputClasses = outputClasses;
-      return true;
     }
   }
 
   public static class R8PartialD8DesugarSubCompilationConfiguration
       extends R8PartialSubCompilationConfiguration {
 
+    private Collection<DexProgramClass> outputClasses;
+
     public R8PartialD8DesugarSubCompilationConfiguration(Timing timing) {
       super(timing);
     }
+
+    public Collection<DexProgramClass> getOutputClasses() {
+      assert outputClasses != null;
+      return outputClasses;
+    }
+
+    @Override
+    public void writeApplication(
+        Collection<DexProgramClass> outputClasses, InternalOptions options) {
+      this.outputClasses = outputClasses;
+    }
   }
 
   public static class R8PartialR8SubCompilationConfiguration
       extends R8PartialSubCompilationConfiguration {
 
+    private Collection<DexProgramClass> desugaringOutputClasses;
     private Collection<DexProgramClass> dexingOutputClasses;
 
     public R8PartialR8SubCompilationConfiguration(
-        Collection<DexProgramClass> dexingOutputClasses, Timing timing) {
+        Collection<DexProgramClass> desugaringOutputClasses,
+        Collection<DexProgramClass> dexingOutputClasses,
+        Timing timing) {
       super(timing);
+      this.desugaringOutputClasses = desugaringOutputClasses;
       this.dexingOutputClasses = dexingOutputClasses;
     }
 
@@ -89,6 +104,15 @@
       return dexingOutputClasses;
     }
 
+    public DirectMappedDexApplication commitDesugaringOutputClasses(
+        DirectMappedDexApplication app) {
+      assert app.classes().isEmpty();
+      DirectMappedDexApplication newApp =
+          app.builder().addProgramClasses(desugaringOutputClasses).build();
+      desugaringOutputClasses = null;
+      return newApp;
+    }
+
     public void commitDexingOutputClasses(AppView<AppInfoWithClassHierarchy> appView) {
       DirectMappedDexApplication newApp =
           appView
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicPreviewPatternsTest.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicPreviewPatternsTest.java
index 791d1ee..f102830 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicPreviewPatternsTest.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicPreviewPatternsTest.java
@@ -61,9 +61,6 @@
         .inspectD8Input(
             inspector ->
                 assertTrue(inspector.hasExactlyProgramClasses(C1.class, C2.class, Main.class)))
-        .inspectR8Input(
-            inspector ->
-                assertTrue(inspector.hasExactlyProgramClasses(A1.class, A2.class, B.class)))
         .inspect(
             inspector ->
                 assertTrue(inspector.hasExactlyProgramClasses(C1.class, C2.class, Main.class)))
@@ -87,8 +84,6 @@
             inspector ->
                 assertTrue(
                     inspector.hasExactlyProgramClasses(B.class, C1.class, C2.class, Main.class)))
-        .inspectR8Input(
-            inspector -> assertTrue(inspector.hasExactlyProgramClasses(A1.class, A2.class)))
         .inspect(
             inspector ->
                 assertTrue(
@@ -113,8 +108,6 @@
             inspector ->
                 assertTrue(
                     inspector.hasExactlyProgramClasses(C1.class, C2.class, B.class, Main.class)))
-        .inspectR8Input(
-            inspector -> assertTrue(inspector.hasExactlyProgramClasses(A1.class, A2.class)))
         .inspect(
             inspector ->
                 assertTrue(
@@ -140,7 +133,6 @@
                 assertTrue(
                     inspector.hasExactlyProgramClasses(
                         A1.class, A2.class, C1.class, C2.class, Main.class)))
-        .inspectR8Input(inspector -> assertTrue(inspector.hasExactlyProgramClasses(B.class)))
         .inspect(
             inspector ->
                 assertTrue(
@@ -168,7 +160,6 @@
                 assertTrue(
                     inspector.hasExactlyProgramClasses(
                         A1.class, A2.class, C1.class, C2.class, Main.class)))
-        .inspectR8Input(inspector -> assertTrue(inspector.hasExactlyProgramClasses(B.class)))
         .inspect(
             inspector ->
                 assertTrue(
@@ -193,10 +184,6 @@
         .compile()
         .inspectD8Input(
             inspector -> assertTrue(inspector.hasExactlyProgramClasses(C1.class, Main.class)))
-        .inspectR8Input(
-            inspector ->
-                assertTrue(
-                    inspector.hasExactlyProgramClasses(A1.class, A2.class, B.class, C2.class)))
         .inspect(inspector -> assertTrue(inspector.hasExactlyProgramClasses(C1.class, Main.class)))
         .run(parameters.getRuntime(), Main.class, ALL_TYPE_NAMES)
         .assertSuccessWithOutputLines(
@@ -222,10 +209,6 @@
         .compile()
         .inspectD8Input(
             inspector -> assertTrue(inspector.hasExactlyProgramClasses(A1.class, Main.class)))
-        .inspectR8Input(
-            inspector ->
-                assertTrue(
-                    inspector.hasExactlyProgramClasses(A2.class, B.class, C1.class, C2.class)))
         .inspect(inspector -> assertTrue(inspector.hasExactlyProgramClasses(A1.class, Main.class)))
         .run(parameters.getRuntime(), Main.class, ALL_TYPE_NAMES)
         .assertSuccessWithOutputLines(
@@ -250,10 +233,6 @@
         .compile()
         .inspectD8Input(
             inspector -> assertTrue(inspector.hasExactlyProgramClasses(B.class, Main.class)))
-        .inspectR8Input(
-            inspector ->
-                assertTrue(
-                    inspector.hasExactlyProgramClasses(A1.class, A2.class, C1.class, C2.class)))
         .inspect(inspector -> assertTrue(inspector.hasExactlyProgramClasses(B.class, Main.class)))
         .run(parameters.getRuntime(), Main.class, ALL_TYPE_NAMES)
         .assertSuccessWithOutputLines(
diff --git a/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicTest.java b/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicTest.java
index a3b2251..95eed20 100644
--- a/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicTest.java
+++ b/src/test/java/com/android/tools/r8/partial/PartialCompilationBasicTest.java
@@ -35,12 +35,6 @@
         .addKeepMainRule(Main.class)
         .setR8PartialConfiguration(builder -> builder.includeAll().excludeClasses(A.class))
         .compile()
-        .inspectR8Input(
-            inspector -> {
-              assertThat(inspector.programClass(A.class), isAbsent());
-              assertThat(inspector.programClass(B.class), isPresent());
-              assertThat(inspector.programClass(Main.class), isPresent());
-            })
         .inspectD8Input(
             inspector -> {
               assertThat(inspector.programClass(A.class), isPresent());
@@ -65,14 +59,6 @@
         .addKeepMainRule(Main.class)
         .setR8PartialConfiguration(builder -> builder.includeAll().excludeClasses(B.class))
         .compile()
-        .inspectR8Input(
-            inspector -> {
-              // TODO(b/309743298): These are all present as inspection currently also look at
-              //  classpath.
-              assertThat(inspector.programClass(A.class), isPresent());
-              assertThat(inspector.programClass(B.class), isAbsent());
-              assertThat(inspector.programClass(Main.class), isPresent());
-            })
         .inspectD8Input(
             inspector -> {
               // TODO(b/309743298): These are all present as inspection currently also look at
diff --git a/src/test/testbase/java/com/android/tools/r8/R8PartialTestBuilder.java b/src/test/testbase/java/com/android/tools/r8/R8PartialTestBuilder.java
index c18c4c7..14df886 100644
--- a/src/test/testbase/java/com/android/tools/r8/R8PartialTestBuilder.java
+++ b/src/test/testbase/java/com/android/tools/r8/R8PartialTestBuilder.java
@@ -137,17 +137,11 @@
       Box<List<ProguardConfigurationRule>> syntheticProguardRulesConsumer,
       StringBuilder proguardMapBuilder)
       throws CompilationFailedException {
-    Box<AndroidApp> r8InputAppBox = new Box<>();
     Box<AndroidApp> d8InputAppBox = new Box<>();
-    Box<AndroidApp> r8OutputAppBox = new Box<>();
-    Box<AndroidApp> d8OutputAppBox = new Box<>();
     Consumer<InternalOptions> configureR8PartialCompilation =
         options -> {
           options.partialCompilationConfiguration = getPartialConfiguration();
-          options.partialCompilationConfiguration.r8InputAppConsumer = r8InputAppBox::set;
           options.partialCompilationConfiguration.d8InputAppConsumer = d8InputAppBox::set;
-          options.partialCompilationConfiguration.r8OutputAppConsumer = r8OutputAppBox::set;
-          options.partialCompilationConfiguration.d8OutputAppConsumer = d8OutputAppBox::set;
         };
     ToolHelper.runAndBenchmarkR8PartialWithoutResult(
         builder, configureR8PartialCompilation.andThen(optionsConsumer), benchmarkResults);
@@ -166,10 +160,7 @@
         resourceShrinkerOutput,
         resourceShrinkerOutputForFeatures,
         buildMetadata != null ? buildMetadata.get() : null,
-        r8InputAppBox.get(),
-        d8InputAppBox.get(),
-        r8OutputAppBox.get(),
-        d8OutputAppBox.get());
+        d8InputAppBox.get());
   }
 
   @Override
diff --git a/src/test/testbase/java/com/android/tools/r8/R8PartialTestCompileResult.java b/src/test/testbase/java/com/android/tools/r8/R8PartialTestCompileResult.java
index 3c53df4..a722661 100644
--- a/src/test/testbase/java/com/android/tools/r8/R8PartialTestCompileResult.java
+++ b/src/test/testbase/java/com/android/tools/r8/R8PartialTestCompileResult.java
@@ -20,10 +20,7 @@
 public class R8PartialTestCompileResult
     extends R8TestCompileResultBase<R8PartialTestCompileResult> {
 
-  private final AndroidApp r8InputApp;
   private final AndroidApp d8InputApp;
-  private final AndroidApp r8OutputApp;
-  private final AndroidApp d8OutputApp;
 
   R8PartialTestCompileResult(
       TestState state,
@@ -40,10 +37,7 @@
       Path resourceShrinkerOutput,
       HashMap<String, Path> resourceShrinkerOutputForFeatures,
       R8BuildMetadata buildMetadata,
-      AndroidApp r8InputApp,
-      AndroidApp d8InputApp,
-      AndroidApp r8OutputApp,
-      AndroidApp d8OutputApp) {
+      AndroidApp d8InputApp) {
     super(
         state,
         outputMode,
@@ -59,10 +53,7 @@
         resourceShrinkerOutput,
         resourceShrinkerOutputForFeatures,
         buildMetadata);
-    this.r8InputApp = r8InputApp;
     this.d8InputApp = d8InputApp;
-    this.r8OutputApp = r8OutputApp;
-    this.d8OutputApp = d8OutputApp;
   }
 
   @Override
@@ -70,21 +61,6 @@
     return this;
   }
 
-  public CodeInspector inspectorR8Input() throws IOException {
-    return new CodeInspector(r8InputApp);
-  }
-
-  public CodeInspector inspectorR8Input(Consumer<InternalOptions> debugOptionsConsumer)
-      throws IOException {
-    return new CodeInspector(r8InputApp, debugOptionsConsumer);
-  }
-
-  public <E extends Throwable> R8PartialTestCompileResult inspectR8Input(
-      ThrowingConsumer<CodeInspector, E> consumer) throws IOException, E {
-    consumer.accept(inspectorR8Input());
-    return self();
-  }
-
   public CodeInspector inspectorD8Input() throws IOException {
     return new CodeInspector(d8InputApp);
   }