Unify predicates for virtual methods/targets.

Change-Id: I8e91fa57fb6017ad0a913dba23eee3f4817df3fc
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
index afdc15b..4656408 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
@@ -212,7 +212,7 @@
       // default interface methods, it is expected they are targeted with invoke-direct.
       return this.itf && desugaringEnabled ? Type.DIRECT : Type.SUPER;
     }
-    if (!encodedMethod.isVirtualMethod()) {
+    if (!encodedMethod.isNonPrivateVirtualMethod()) {
       return Type.DIRECT;
     }
     if (encodedMethod.accessFlags.isFinal()) {
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfo.java b/src/main/java/com/android/tools/r8/graph/AppInfo.java
index 86b2cb8..ad19ed4 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -256,16 +256,17 @@
 
   /**
    * Lookup virtual method starting in type and following the super chain.
-   * <p>
-   * This method will resolve the method on the holder of {@code method} and only return a
-   * non-null value if the result of resolution was a non-static, non-private method.
+   *
+   * <p>This method will resolve the method on the holder of {@code method} and only return a
+   * non-null value if the result of resolution was a virtual target.
+   *
+   * <p>TODO(b/140204899): Delete this method as it does resolution and not a "lookup of targets".
    */
   public DexEncodedMethod lookupVirtualTarget(DexType type, DexMethod method) {
     assert checkIfObsolete();
     assert type.isClassType() || type.isArrayType();
     ResolutionResult resolutionResult = resolveMethod(type, method);
-    DexEncodedMethod target = resolutionResult.getSingleTarget();
-    return target == null || target.isVirtualMethod() ? target : null;
+    return resolutionResult.isVirtualTarget() ? resolutionResult.getSingleTarget() : null;
   }
 
   /**
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index dbd455b..a928529 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -221,11 +221,11 @@
   }
 
   public OptionalBool isLibraryMethodOverride() {
-    return isVirtualMethod() ? isLibraryMethodOverride : OptionalBool.FALSE;
+    return isNonPrivateVirtualMethod() ? isLibraryMethodOverride : OptionalBool.FALSE;
   }
 
   public void setLibraryMethodOverride(OptionalBool isLibraryMethodOverride) {
-    assert isVirtualMethod();
+    assert isNonPrivateVirtualMethod();
     assert !isLibraryMethodOverride.isUnknown();
     assert isLibraryMethodOverride.isPossiblyFalse()
             || this.isLibraryMethodOverride.isPossiblyTrue()
@@ -287,12 +287,19 @@
   }
 
   /**
-   * Returns true if this method can be invoked via invoke-virtual, invoke-super or
-   * invoke-interface.
+   * Returns true if this method can be invoked via invoke-virtual/interface.
+   *
+   * <p>Note that also private methods can be the target of a virtual invoke. In such cases, the
+   * validity of the invoke depends on the access granted to the call site.
    */
   public boolean isVirtualMethod() {
     checkIfObsolete();
-    return !accessFlags.isStatic() && !accessFlags.isPrivate() && !accessFlags.isConstructor();
+    return !accessFlags.isStatic() && !accessFlags.isConstructor();
+  }
+
+  public boolean isNonPrivateVirtualMethod() {
+    checkIfObsolete();
+    return !isPrivateMethod() && isVirtualMethod();
   }
 
   /**
diff --git a/src/main/java/com/android/tools/r8/graph/ResolutionResult.java b/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
index 2c60a43..4854741 100644
--- a/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
+++ b/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
@@ -3,8 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.graph;
 
-import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
-
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.utils.SetUtils;
 import com.google.common.collect.Sets;
@@ -58,11 +56,7 @@
 
   // TODO(b/145187573): Remove this and use proper access checks.
   @Deprecated
-  public abstract boolean isValidVirtualTarget();
-
-  // TODO(b/145187573): Remove this and use proper access checks.
-  @Deprecated
-  public abstract boolean isValidVirtualTargetForDynamicDispatch();
+  public abstract boolean isVirtualTarget();
 
   /** Lookup the single target of an invoke-special on this resolution result if possible. */
   public abstract DexEncodedMethod lookupInvokeSpecialTarget(
@@ -90,12 +84,6 @@
     private final DexClass resolvedHolder;
     private final DexEncodedMethod resolvedMethod;
 
-    // TODO(b/145187573): Remove this and use proper access checks.
-    @Deprecated
-    public static boolean isValidVirtualTarget(DexEncodedMethod target) {
-      return !target.accessFlags.isStatic() && !target.accessFlags.isConstructor();
-    }
-
     public SingleResolutionResult(
         DexClass initialResolutionHolder,
         DexClass resolvedHolder,
@@ -136,20 +124,11 @@
     @Override
     public boolean isAccessibleForVirtualDispatchFrom(
         DexProgramClass context, AppInfoWithSubtyping appInfo) {
-      // If a private method is accessible (which implies it is via its nest), then it is a valid
-      // virtual dispatch target if non-static.
-      return isAccessibleFrom(context, appInfo)
-          && (resolvedMethod.isVirtualMethod()
-              || (resolvedMethod.isPrivateMethod() && !resolvedMethod.isStatic()));
+      return resolvedMethod.isVirtualMethod() && isAccessibleFrom(context, appInfo);
     }
 
     @Override
-    public boolean isValidVirtualTarget() {
-      return isValidVirtualTarget(resolvedMethod);
-    }
-
-    @Override
-    public boolean isValidVirtualTargetForDynamicDispatch() {
+    public boolean isVirtualTarget() {
       return resolvedMethod.isVirtualMethod();
     }
 
@@ -304,12 +283,16 @@
     @Override
     // TODO(b/140204899): Leverage refined receiver type if available.
     public Set<DexEncodedMethod> lookupVirtualTargets(AppInfoWithSubtyping appInfo) {
-      assert isValidVirtualTarget();
+      if (resolvedMethod.isPrivateMethod()) {
+        // If the resolved reference is private there is no dispatch.
+        // This is assuming that the method is accessible, which implies self/nest access.
+        return Collections.singleton(resolvedMethod);
+      }
+      assert resolvedMethod.isNonPrivateVirtualMethod();
       // First add the target for receiver type method.type.
-      DexEncodedMethod encodedMethod = getSingleTarget();
-      Set<DexEncodedMethod> result = SetUtils.newIdentityHashSet(encodedMethod);
+      Set<DexEncodedMethod> result = SetUtils.newIdentityHashSet(resolvedMethod);
       // Add all matching targets from the subclass hierarchy.
-      DexMethod method = encodedMethod.method;
+      DexMethod method = resolvedMethod.method;
       // TODO(b/140204899): Instead of subtypes of holder, we could iterate subtypes of refined
       //   receiver type if available.
       for (DexType type : appInfo.subtypes(method.holder)) {
@@ -317,7 +300,7 @@
         if (!clazz.isInterface()) {
           ResolutionResult methods = appInfo.resolveMethodOnClass(clazz, method);
           DexEncodedMethod target = methods.getSingleTarget();
-          if (target != null && target.isVirtualMethod()) {
+          if (target != null && target.isNonPrivateVirtualMethod()) {
             result.add(target);
           }
         }
@@ -328,43 +311,44 @@
     @Override
     // TODO(b/140204899): Leverage refined receiver type if available.
     public Set<DexEncodedMethod> lookupInterfaceTargets(AppInfoWithSubtyping appInfo) {
-      assert isValidVirtualTarget();
+      if (resolvedMethod.isPrivateMethod()) {
+        // If the resolved reference is private there is no dispatch.
+        // This is assuming that the method is accessible, which implies self/nest access.
+        assert resolvedMethod.hasCode();
+        return Collections.singleton(resolvedMethod);
+      }
+      assert resolvedMethod.isNonPrivateVirtualMethod();
       Set<DexEncodedMethod> result = Sets.newIdentityHashSet();
-      if (isSingleResolution()) {
-        // Add default interface methods to the list of targets.
-        //
-        // This helps to make sure we take into account synthesized lambda classes
-        // that we are not aware of. Like in the following example, we know that all
-        // classes, XX in this case, override B::bar(), but there are also synthesized
-        // classes for lambda which don't, so we still need default method to be live.
-        //
-        //   public static void main(String[] args) {
-        //     X x = () -> {};
-        //     x.bar();
-        //   }
-        //
-        //   interface X {
-        //     void foo();
-        //     default void bar() { }
-        //   }
-        //
-        //   class XX implements X {
-        //     public void foo() { }
-        //     public void bar() { }
-        //   }
-        //
-        DexEncodedMethod singleTarget = getSingleTarget();
-        if (singleTarget.hasCode()) {
-          DexProgramClass holder =
-              asProgramClassOrNull(appInfo.definitionFor(singleTarget.method.holder));
-          if (appInfo.hasAnyInstantiatedLambdas(holder)) {
-            result.add(singleTarget);
-          }
+      // Add default interface methods to the list of targets.
+      //
+      // This helps to make sure we take into account synthesized lambda classes
+      // that we are not aware of. Like in the following example, we know that all
+      // classes, XX in this case, override B::bar(), but there are also synthesized
+      // classes for lambda which don't, so we still need default method to be live.
+      //
+      //   public static void main(String[] args) {
+      //     X x = () -> {};
+      //     x.bar();
+      //   }
+      //
+      //   interface X {
+      //     void foo();
+      //     default void bar() { }
+      //   }
+      //
+      //   class XX implements X {
+      //     public void foo() { }
+      //     public void bar() { }
+      //   }
+      //
+      if (resolvedMethod.hasCode()) {
+        DexProgramClass holder = resolvedHolder.asProgramClass();
+        if (appInfo.hasAnyInstantiatedLambdas(holder)) {
+          result.add(resolvedMethod);
         }
       }
 
-      DexEncodedMethod encodedMethod = getSingleTarget();
-      DexMethod method = encodedMethod.method;
+      DexMethod method = resolvedMethod.method;
       Consumer<DexEncodedMethod> addIfNotAbstract =
           m -> {
             if (!m.accessFlags.isAbstract()) {
@@ -454,12 +438,7 @@
     }
 
     @Override
-    public boolean isValidVirtualTarget() {
-      return true;
-    }
-
-    @Override
-    public boolean isValidVirtualTargetForDynamicDispatch() {
+    public boolean isVirtualTarget() {
       return true;
     }
   }
@@ -493,12 +472,7 @@
     }
 
     @Override
-    public boolean isValidVirtualTarget() {
-      return false;
-    }
-
-    @Override
-    public boolean isValidVirtualTargetForDynamicDispatch() {
+    public boolean isVirtualTarget() {
       return false;
     }
   }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java b/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java
index 0e6d2a3..ade31ca 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java
@@ -180,7 +180,7 @@
               method -> {
                 ResolutionResult resolution =
                     appView.appInfo().resolveMethod(method.holder, method, isInterface);
-                if (resolution.isValidVirtualTarget()) {
+                if (resolution.isVirtualTarget()) {
                   return resolution.lookupVirtualDispatchTargets(isInterface, appView.appInfo());
                 }
                 return null;
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
index bf556c8..dc425e4 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
@@ -643,7 +643,8 @@
   }
 
   private boolean canInvokeTargetWithInvokeVirtual(DexEncodedMethod target) {
-    return target.isVirtualMethod() && appView.isInterface(target.method.holder).isFalse();
+    return target.isNonPrivateVirtualMethod()
+        && appView.isInterface(target.method.holder).isFalse();
   }
 
   private boolean hasAccessToInvokeTargetFromContext(DexEncodedMethod target, DexType context) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
index a4fc2e9..565af2f 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
@@ -333,7 +333,7 @@
   private boolean isRetargetMethod(DexLibraryClass holder, DexEncodedMethod method) {
     assert needsLibraryInfo();
     assert holder.type == method.method.holder;
-    assert method.isVirtualMethod();
+    assert method.isNonPrivateVirtualMethod();
     if (method.isFinal()) {
       return false;
     }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java b/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java
index 133eff3..00c797d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CallSiteOptimizationInfoPropagator.java
@@ -88,7 +88,7 @@
           ResolutionResult resolutionResult =
               appView.appInfo().resolveMethod(invokedMethod.holder, invokedMethod);
           // For virtual and interface calls, proceed on valid results only (since it's enforced).
-          if (!resolutionResult.isValidVirtualTarget()) {
+          if (!resolutionResult.isVirtualTarget()) {
             continue;
           }
           // If the resolution ended up with a single target, check if it is a library override.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
index e0219c5..b95f69e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
@@ -352,7 +352,7 @@
     // resolution result.
     ResolutionResult resolutionResult =
         appView.appInfo().resolveMethod(method.holder, method, isInterface);
-    if (!resolutionResult.isValidVirtualTarget()) {
+    if (!resolutionResult.isVirtualTarget()) {
       return ConstraintWithTarget.NEVER;
     }
 
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java
index 194b84a..aec5219 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/UnusedArgumentsCollector.java
@@ -291,7 +291,7 @@
     if (method.getCode() == null || !method.getCode().isCfCode()) {
       return null;
     }
-    if (method.isVirtualMethod()) {
+    if (method.isNonPrivateVirtualMethod()) {
       // Abort if the method overrides another method, or if the method is overridden. In both cases
       // an unused argument cannot be removed unless it is unused in all of the related methods in
       // the hierarchy.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
index c522ff3..d4d43f4 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/InlineCandidateProcessor.java
@@ -859,13 +859,14 @@
 
     // We should not inline a method if the invocation has type interface or virtual and the
     // signature of the invocation resolves to a private or static method.
+    // TODO(b/147212189): Why not inline private methods? If access is permitted it is valid.
     ResolutionResult resolutionResult = appView.appInfo().resolveMethod(callee.holder, callee);
     if (resolutionResult.isSingleResolution()
-        && !resolutionResult.getSingleTarget().isVirtualMethod()) {
+        && !resolutionResult.getSingleTarget().isNonPrivateVirtualMethod()) {
       return null;
     }
 
-    if (!singleTarget.isVirtualMethod()) {
+    if (!singleTarget.isNonPrivateVirtualMethod()) {
       return null;
     }
     if (method == singleTarget) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
index a11f309..8fee6c5 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
@@ -135,7 +135,7 @@
         return;
       }
 
-      assert method.isVirtualMethod();
+      assert method.isNonPrivateVirtualMethod();
       assert context == null;
 
       Map<InvokeVirtual, InliningInfo> invokesToInline = new IdentityHashMap<>();
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 4e248d9..9b5029f 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -26,7 +26,6 @@
 import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.graph.PresortedComparable;
 import com.android.tools.r8.graph.ResolutionResult;
-import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
 import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
 import com.android.tools.r8.ir.code.Invoke.Type;
 import com.android.tools.r8.utils.CollectionUtils;
@@ -979,7 +978,7 @@
 
   private DexEncodedMethod validateSingleVirtualTarget(
       DexEncodedMethod singleTarget, DexEncodedMethod resolutionResult) {
-    assert SingleResolutionResult.isValidVirtualTarget(resolutionResult);
+    assert resolutionResult.isVirtualMethod();
 
     if (singleTarget == null || singleTarget == DexEncodedMethod.SENTINEL) {
       return null;
@@ -996,7 +995,7 @@
 
   private boolean isInvalidSingleVirtualTarget(
       DexEncodedMethod singleTarget, DexEncodedMethod resolutionResult) {
-    assert SingleResolutionResult.isValidVirtualTarget(resolutionResult);
+    assert resolutionResult.isVirtualMethod();
     // Art978_virtual_interfaceTest correctly expects an IncompatibleClassChangeError exception
     // at runtime.
     return !singleTarget.accessFlags.isAtLeastAsVisibleAs(resolutionResult.accessFlags);
@@ -1039,11 +1038,10 @@
     // from the runtime type of the receiver.
     if (receiverLowerBoundType != null) {
       if (receiverLowerBoundType.getClassType() == refinedReceiverType) {
-        if (resolutionResult.isSingleResolution()
-            && resolutionResult.isValidVirtualTargetForDynamicDispatch()) {
+        if (resolutionResult.isSingleResolution() && resolutionResult.isVirtualTarget()) {
           ResolutionResult refinedResolutionResult = resolveMethod(refinedReceiverType, method);
           if (refinedResolutionResult.isSingleResolution()
-              && refinedResolutionResult.isValidVirtualTargetForDynamicDispatch()) {
+              && refinedResolutionResult.isVirtualTarget()) {
             return validateSingleVirtualTarget(
                 refinedResolutionResult.getSingleTarget(), resolutionResult.getSingleTarget());
           }
@@ -1081,7 +1079,7 @@
     // First get the target for the holder type.
     ResolutionResult topMethod = resolveMethodOnClass(holder, method);
     // We might hit none or multiple targets. Both make this fail at runtime.
-    if (!topMethod.isSingleResolution() || !topMethod.isValidVirtualTarget()) {
+    if (!topMethod.isSingleResolution() || !topMethod.isVirtualTarget()) {
       method.setSingleVirtualMethodCache(refinedReceiverType, null);
       return null;
     }
@@ -1223,11 +1221,10 @@
     if (receiverLowerBoundType != null) {
       if (receiverLowerBoundType.getClassType() == refinedReceiverType) {
         ResolutionResult resolutionResult = resolveMethod(method.holder, method, true);
-        if (resolutionResult.isSingleResolution()
-            && resolutionResult.isValidVirtualTargetForDynamicDispatch()) {
+        if (resolutionResult.isSingleResolution() && resolutionResult.isVirtualTarget()) {
           ResolutionResult refinedResolutionResult = resolveMethod(refinedReceiverType, method);
           if (refinedResolutionResult.isSingleResolution()
-              && refinedResolutionResult.isValidVirtualTargetForDynamicDispatch()) {
+              && refinedResolutionResult.isVirtualTarget()) {
             return validateSingleVirtualTarget(
                 refinedResolutionResult.getSingleTarget(), resolutionResult.getSingleTarget());
           }
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 1fa2300..ce71c31 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -1416,7 +1416,7 @@
     // It is valid to have an invoke-direct instruction in a default interface method that
     // targets another default method in the same interface (see testInvokeSpecialToDefault-
     // Method). In a class, that would lead to a verification error.
-    if (encodedMethod.isVirtualMethod()
+    if (encodedMethod.isNonPrivateVirtualMethod()
         && virtualMethodsTargetedByInvokeDirect.add(encodedMethod.method)) {
       enqueueMarkMethodLiveAction(clazz, encodedMethod, reason);
     }
@@ -1658,7 +1658,7 @@
   }
 
   private void markResolutionAsLive(DexClass libraryClass, ResolutionResult resolution) {
-    if (resolution.isValidVirtualTarget()) {
+    if (resolution.isVirtualTarget()) {
       DexEncodedMethod target = resolution.getSingleTarget();
       DexProgramClass targetHolder = getProgramClassOrNull(target.method.holder);
       if (targetHolder != null
@@ -2003,8 +2003,7 @@
     // Otherwise, the resolution target is marked and cached, and all possible targets identified.
     resolution = findAndMarkResolutionTarget(method, interfaceInvoke, reason);
     virtualTargetsMarkedAsReachable.put(method, resolution);
-    if (resolution.isUnresolved()
-        || !SingleResolutionResult.isValidVirtualTarget(resolution.method)) {
+    if (resolution.isUnresolved() || !resolution.method.isVirtualMethod()) {
       // There is no valid resolution, so any call will lead to a runtime exception.
       return;
     }
@@ -2035,7 +2034,7 @@
       MarkedResolutionTarget reason,
       BiPredicate<DexProgramClass, DexEncodedMethod> possibleTargetsFilter,
       DexEncodedMethod encodedPossibleTarget) {
-    assert encodedPossibleTarget.isVirtualMethod() || encodedPossibleTarget.isPrivateMethod();
+    assert encodedPossibleTarget.isVirtualMethod();
     assert !encodedPossibleTarget.isAbstract();
     DexMethod possibleTarget = encodedPossibleTarget.method;
     DexProgramClass clazz = getProgramClassOrNull(possibleTarget.holder);
@@ -2543,7 +2542,7 @@
       DexProgramClass clazz, DexEncodedMethod method) {
     assert method.isVirtualMethod();
 
-    if (method.isAbstract()) {
+    if (method.isAbstract() || method.isPrivateMethod()) {
       return false;
     }
 
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
index bd05dc3..b842680 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -533,7 +533,7 @@
       }
       ResolutionResult resolutionResult =
           appView.appInfo().resolveMethod(originalClazz, method.method);
-      if (!resolutionResult.isValidVirtualTarget() || !resolutionResult.isSingleResolution()) {
+      if (!resolutionResult.isVirtualTarget() || !resolutionResult.isSingleResolution()) {
         return;
       }
       DexEncodedMethod methodToKeep = resolutionResult.getSingleTarget();
diff --git a/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java b/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
index 27c7724..e290d51 100644
--- a/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
@@ -228,7 +228,7 @@
     Assert.assertNotNull(
         appInfo.resolveMethod(toType(invokeReceiver, appInfo), method).getSingleTarget());
     ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
-    if (resolutionResult.isValidVirtualTarget()) {
+    if (resolutionResult.isVirtualTarget()) {
       Set<DexEncodedMethod> targets = resolutionResult.lookupVirtualTargets(appInfo);
       Set<DexType> targetHolders =
           targets.stream().map(m -> m.method.holder).collect(Collectors.toSet());
diff --git a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest.java b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest.java
index 82452a8..c90b6e4 100644
--- a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentInterfaceTest.java
@@ -122,7 +122,7 @@
         appInfo.resolveMethodOnInterface(methodOnB.holder, methodOnB);
     DexEncodedMethod resolved = resolutionResult.getSingleTarget();
     assertEquals(methodOnB, resolved.method);
-    assertFalse(resolutionResult.isValidVirtualTarget());
+    assertFalse(resolutionResult.isVirtualTarget());
     DexEncodedMethod singleVirtualTarget =
         appInfo.lookupSingleInterfaceTarget(methodOnB, methodOnB.holder);
     Assert.assertNull(singleVirtualTarget);
@@ -133,7 +133,7 @@
     ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(methodOnB.holder, methodOnB);
     DexEncodedMethod resolved = resolutionResult.getSingleTarget();
     assertEquals(methodOnB, resolved.method);
-    assertFalse(resolutionResult.isValidVirtualTarget());
+    assertFalse(resolutionResult.isVirtualTarget());
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentTest.java b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentTest.java
index 702eca9..f41a60f 100644
--- a/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/VirtualOverrideOfStaticMethodWithVirtualParentTest.java
@@ -168,7 +168,7 @@
     ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(methodOnB.holder, methodOnB);
     DexEncodedMethod resolved = resolutionResult.getSingleTarget();
     assertEquals(methodOnA, resolved.method);
-    assertFalse(resolutionResult.isValidVirtualTarget());
+    assertFalse(resolutionResult.isVirtualTarget());
     DexEncodedMethod singleVirtualTarget =
         appInfo.lookupSingleVirtualTarget(methodOnB, methodOnB.holder);
     Assert.assertNull(singleVirtualTarget);
@@ -179,7 +179,7 @@
     ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(methodOnB.holder, methodOnB);
     DexEncodedMethod resolved = resolutionResult.getSingleTarget();
     assertEquals(methodOnA, resolved.method);
-    assertFalse(resolutionResult.isValidVirtualTarget());
+    assertFalse(resolutionResult.isVirtualTarget());
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
index 071fb4f..1051e28 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
@@ -134,7 +134,7 @@
 
   @Override
   public boolean isVirtual() {
-    return dexMethod.isVirtualMethod();
+    return dexMethod.isNonPrivateVirtualMethod();
   }
 
   @Override