Ensure all methods in method access info collection resolve

Change-Id: Ia29424888766c0ed626dada49b0258c6515d35a9
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index 3e0bc95..532abbd 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -1099,6 +1099,17 @@
                 @Override
                 public void onJoin() {
                   appView.withClassHierarchy().setAppInfo(result);
+                  assert verifyLensRewriting();
+                }
+
+                private boolean verifyLensRewriting() {
+                  if (appView.hasLiveness()) {
+                    AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
+                    MethodAccessInfoCollection methodAccessInfoCollection =
+                        appViewWithLiveness.appInfo().getMethodAccessInfoCollection();
+                    methodAccessInfoCollection.modifier().commit(appViewWithLiveness);
+                  }
+                  return true;
                 }
               },
               new ThreadTask() {
diff --git a/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java b/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java
index 2671841..542a558 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java
@@ -9,6 +9,8 @@
 import com.android.tools.r8.graph.lens.GraphLens;
 import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.ir.code.InvokeType;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.shaking.Enqueuer;
 import com.android.tools.r8.utils.ConsumerUtils;
 import com.android.tools.r8.utils.Timing;
 import com.android.tools.r8.utils.collections.ProgramMethodSet;
@@ -347,6 +349,54 @@
       invokes.keySet().removeIf(predicate);
     }
 
+    public void removeNonResolving(
+        AppView<? extends AppInfoWithClassHierarchy> appView, Enqueuer enqueuer) {
+      // TODO(b/313365881): Should use non-legacy resolution, but this fails.
+      removeIf(
+          method -> {
+            MethodResolutionResult result =
+                appView.appInfo().unsafeResolveMethodDueToDexFormatLegacy(method);
+            if (result.isFailedResolution()
+                || result.isSignaturePolymorphicResolution(method, appView.dexItemFactory())) {
+              return true;
+            }
+            if (result.hasProgramResult()) {
+              ProgramMethod resolvedMethod = result.getResolvedProgramMethod();
+              // Guard against an unusual case where the invoke resolves to a program method but the
+              // invoke is invalid (e.g., invoke-interface to a non-interface), such that the
+              // resolved method is not retained after all.
+              if (!enqueuer.isMethodLive(resolvedMethod)
+                  && !enqueuer.isMethodTargeted(resolvedMethod)) {
+                return true;
+              }
+            }
+            return false;
+          });
+    }
+
+    public boolean verifyNoNonResolving(AppView<AppInfoWithLiveness> appView) {
+      verifyNoNonResolving(appView, directInvokes);
+      verifyNoNonResolving(appView, interfaceInvokes);
+      verifyNoNonResolving(appView, staticInvokes);
+      verifyNoNonResolving(appView, superInvokes);
+      verifyNoNonResolving(appView, virtualInvokes);
+      return true;
+    }
+
+    private void verifyNoNonResolving(
+        AppView<AppInfoWithLiveness> appView, Map<DexMethod, ?> invokes) {
+      if (!isThrowingMap(invokes)) {
+        for (DexMethod method : invokes.keySet()) {
+          MethodResolutionResult result =
+              appView.appInfo().unsafeResolveMethodDueToDexFormatLegacy(method);
+          assert !result.isFailedResolution()
+              : "Unexpected method that does not resolve: " + method.toSourceString();
+          assert !result.isSignaturePolymorphicResolution(method, appView.dexItemFactory())
+              : "Unexpected signature polymorphic resolution: " + method.toSourceString();
+        }
+      }
+    }
+
     public MethodAccessInfoCollection build() {
       return new MethodAccessInfoCollection(
           directInvokes, interfaceInvokes, staticInvokes, superInvokes, virtualInvokes);
@@ -387,5 +437,9 @@
       collection.forEachSuperInvoke(this::registerInvokeSuperInContexts);
       collection.forEachVirtualInvoke(this::registerInvokeVirtualInContexts);
     }
+
+    public void commit(AppView<AppInfoWithLiveness> appView) {
+      assert verifyNoNonResolving(appView);
+    }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java b/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java
index b0292c6..d0f23ae 100644
--- a/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/lens/GraphLens.java
@@ -36,6 +36,7 @@
 import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeHashMap;
 import com.android.tools.r8.utils.collections.MutableBidirectionalManyToOneRepresentativeMap;
 import com.android.tools.r8.utils.collections.ProgramMethodSet;
+import com.android.tools.r8.verticalclassmerging.VerticalClassMergerGraphLens;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
@@ -458,6 +459,10 @@
     return false;
   }
 
+  public VerticalClassMergerGraphLens asVerticalClassMergerLens() {
+    return null;
+  }
+
   @SuppressWarnings("ReferenceEquality")
   public boolean assertFieldsNotModified(Iterable<DexEncodedField> fields) {
     for (DexEncodedField field : fields) {
diff --git a/src/main/java/com/android/tools/r8/graph/lens/GraphLensUtils.java b/src/main/java/com/android/tools/r8/graph/lens/GraphLensUtils.java
new file mode 100644
index 0000000..b7175d3
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/lens/GraphLensUtils.java
@@ -0,0 +1,26 @@
+// Copyright (c) 2023, 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.graph.lens;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+
+public class GraphLensUtils {
+
+  public static Deque<NonIdentityGraphLens> extractNonIdentityLenses(GraphLens lens) {
+    Deque<NonIdentityGraphLens> lenses = new ArrayDeque<>();
+    if (lens.isNonIdentityLens()) {
+      lenses.addFirst(lens.asNonIdentityLens());
+      while (true) {
+        GraphLens previous = lenses.getFirst().getPrevious();
+        if (previous.isNonIdentityLens()) {
+          lenses.addFirst(previous.asNonIdentityLens());
+        } else {
+          break;
+        }
+      }
+    }
+    return lenses;
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java
index 234b353..0ea0a9a 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java
@@ -15,8 +15,10 @@
 import com.android.tools.r8.graph.lens.DefaultNonIdentityGraphLens;
 import com.android.tools.r8.graph.lens.FieldLookupResult;
 import com.android.tools.r8.graph.lens.GraphLens;
+import com.android.tools.r8.graph.lens.GraphLensUtils;
 import com.android.tools.r8.graph.lens.MethodLookupResult;
 import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
+import java.util.Deque;
 import java.util.IdentityHashMap;
 import java.util.Map;
 
@@ -134,10 +136,25 @@
                 rewrittenNonReboundFieldReference, rewrittenReboundFieldReference);
           }
         });
+
+    Deque<NonIdentityGraphLens> lenses = GraphLensUtils.extractNonIdentityLenses(lens);
     nonReboundMethodReferenceToDefinitionMap.forEach(
         (nonReboundMethodReference, reboundMethodReference) -> {
-          DexMethod rewrittenReboundMethodReference =
-              lens.getRenamedMethodSignature(reboundMethodReference, appliedMemberRebindingLens);
+          DexMethod rewrittenReboundMethodReference = reboundMethodReference;
+          for (NonIdentityGraphLens currentLens : lenses) {
+            if (currentLens.isVerticalClassMergerLens()) {
+              // The vertical class merger lens maps merged virtual methods to private methods in
+              // the subclass. Invokes to such virtual methods are mapped to the corresponding
+              // virtual method in the subclass.
+              rewrittenReboundMethodReference =
+                  currentLens
+                      .asVerticalClassMergerLens()
+                      .getNextBridgeMethodSignature(rewrittenReboundMethodReference);
+            } else {
+              rewrittenReboundMethodReference =
+                  currentLens.getNextMethodSignature(rewrittenReboundMethodReference);
+            }
+          }
           DexMethod rewrittenNonReboundMethodReference =
               rewrittenReboundMethodReference.withHolder(
                   lens.lookupType(
diff --git a/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java b/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java
index 5a8e0de..4b4b611 100644
--- a/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java
+++ b/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java
@@ -114,6 +114,7 @@
                 assert false;
               }
             });
+        methodAccessInfoCollectionModifier.commit(appView);
       }
     }
 
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index b4f643a..4cdfc22 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -4257,13 +4257,7 @@
     timing.end();
 
     // Remove mappings for methods that don't resolve in the method access info collection.
-    // TODO(b/313365881): Should use non-legacy resolution, but this fails.
-    methodAccessInfoCollection.removeIf(
-        method -> {
-          MethodResolutionResult result = appInfo.unsafeResolveMethodDueToDexFormatLegacy(method);
-          return result.isFailedResolution()
-              || result.isSignaturePolymorphicResolution(method, appView.dexItemFactory());
-        });
+    methodAccessInfoCollection.removeNonResolving(appView, this);
 
     // Verify all references on the input app before synthesizing definitions.
     assert verifyReferences(appInfo.app());
diff --git a/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMergerGraphLens.java b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMergerGraphLens.java
index 08ca4be..ad653bd 100644
--- a/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMergerGraphLens.java
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMergerGraphLens.java
@@ -108,6 +108,11 @@
   }
 
   @Override
+  public VerticalClassMergerGraphLens asVerticalClassMergerLens() {
+    return this;
+  }
+
+  @Override
   public DexType getPreviousClassType(DexType type) {
     return type;
   }