Allow for synthetic main dex roots as dependencies for final merging

Change-Id: I883cbd1d9ee2af58b1b9fc1ad84916bb101bfa21
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index 09fee09..c4ebfe7 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -1056,7 +1056,7 @@
     return new AppInfoWithLiveness(
         committedItems,
         getClassToFeatureSplitMap().rewrittenWithLens(lens),
-        getMainDexInfo().rewrittenWithLens(lens),
+        getMainDexInfo().rewrittenWithLens(getSyntheticItems(), lens),
         deadProtoTypes,
         getMissingClasses().commitSyntheticItems(committedItems),
         lens.rewriteTypes(liveTypes),
diff --git a/src/main/java/com/android/tools/r8/shaking/MainDexInfo.java b/src/main/java/com/android/tools/r8/shaking/MainDexInfo.java
index 5be14a3..f3f52fd 100644
--- a/src/main/java/com/android/tools/r8/shaking/MainDexInfo.java
+++ b/src/main/java/com/android/tools/r8/shaking/MainDexInfo.java
@@ -276,7 +276,7 @@
     }
   }
 
-  public MainDexInfo rewrittenWithLens(GraphLens lens) {
+  public MainDexInfo rewrittenWithLens(SyntheticItems syntheticItems, GraphLens lens) {
     Set<DexType> modifiedClassList = Sets.newIdentityHashSet();
     classList.forEach(
         type -> rewriteAndApplyIfNotPrimitiveType(lens, type, modifiedClassList::add));
@@ -289,6 +289,9 @@
             // Synthetic finalization is allowed to merge identical classes into the same class. The
             // rewritten type of a traced dependency can therefore be finalized with a traced root.
             rewriteAndApplyIfNotPrimitiveType(lens, type, builder::addDependencyIfNotRoot);
+          } else if (syntheticItems.isFinalized()) {
+            rewriteAndApplyIfNotPrimitiveType(
+                lens, type, builder.addDependencyAllowSyntheticRoot(syntheticItems));
           } else {
             rewriteAndApplyIfNotPrimitiveType(lens, type, builder::addDependency);
           }
@@ -342,6 +345,13 @@
       dependencies.add(type);
     }
 
+    public Consumer<DexType> addDependencyAllowSyntheticRoot(SyntheticItems syntheticItems) {
+      return type -> {
+        assert !roots.contains(type) || syntheticItems.isCommittedSynthetic(type);
+        addDependencyIfNotRoot(type);
+      };
+    }
+
     public void addDependencyIfNotRoot(DexType type) {
       if (roots.contains(type)) {
         return;
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
index 81a06a2..55b5e00 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
@@ -153,7 +153,10 @@
           appView
               .appInfo()
               .rebuildWithMainDexInfo(
-                  appView.appInfo().getMainDexInfo().rewrittenWithLens(result.lens)));
+                  appView
+                      .appInfo()
+                      .getMainDexInfo()
+                      .rewrittenWithLens(appView.getSyntheticItems(), result.lens)));
       appView.setGraphLens(result.lens);
     }
     appView.pruneItems(result.prunedItems);
@@ -170,7 +173,10 @@
           appView
               .appInfo()
               .rebuildWithMainDexInfo(
-                  appView.appInfo().getMainDexInfo().rewrittenWithLens(result.lens)));
+                  appView
+                      .appInfo()
+                      .getMainDexInfo()
+                      .rewrittenWithLens(appView.getSyntheticItems(), result.lens)));
     }
     appView.pruneItems(result.prunedItems);
   }
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 a1f9b48..78c046f 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
@@ -183,6 +183,10 @@
     return baseDefinitionFor.apply(type);
   }
 
+  public boolean isFinalized() {
+    return nextSyntheticId == INVALID_ID_AFTER_SYNTHETIC_FINALIZATION;
+  }
+
   public boolean hasPendingSyntheticClasses() {
     return !pending.isEmpty();
   }
@@ -191,7 +195,7 @@
     return pending.getAllProgramClasses();
   }
 
-  private boolean isCommittedSynthetic(DexType type) {
+  public boolean isCommittedSynthetic(DexType type) {
     return committed.containsType(type);
   }