Return DexClassAndMembers to not have a NO_RESULT instance

Change-Id: I2b9c0728121e65ed4815f39265f425b91d7dd48f
diff --git a/src/main/java/com/android/tools/r8/graph/DexClassAndMethod.java b/src/main/java/com/android/tools/r8/graph/DexClassAndMethod.java
index 9d07cc6..281b58a 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClassAndMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClassAndMethod.java
@@ -6,30 +6,23 @@
 
 import com.android.tools.r8.errors.Unreachable;
 
-public class DexClassAndMethod<C extends DexClass> {
+public class DexClassAndMethod {
 
-  private static final DexClassAndMethod<?> NO_RESULT = new DexClassAndMethod<>(null, null);
+  private final DexClass holder;
+  private final DexEncodedMethod method;
 
-  public final C holder;
-  public final DexEncodedMethod method;
-
-  protected DexClassAndMethod(C holder, DexEncodedMethod method) {
-    assert (holder == null && method == null)
-        || (holder != null && method != null && holder.type == method.method.holder);
+  protected DexClassAndMethod(DexClass holder, DexEncodedMethod method) {
+    assert holder.type == method.method.holder;
     this.holder = holder;
     this.method = method;
   }
 
-  public static <C extends DexClass> DexClassAndMethod<C> createResult(
-      C c, DexEncodedMethod method) {
-    assert c != null;
-    assert method != null;
-    assert c.type == method.method.holder;
-    return new DexClassAndMethod<C>(c, method);
-  }
-
-  public static DexClassAndMethod<?> createNoResult() {
-    return NO_RESULT;
+  public static DexClassAndMethod create(DexClass holder, DexEncodedMethod method) {
+    if (holder.isProgramClass()) {
+      return new ProgramMethod(holder.asProgramClass(), method);
+    } else {
+      return new DexClassAndMethod(holder, method);
+    }
   }
 
   @Override
@@ -42,11 +35,19 @@
     throw new Unreachable("Unsupported attempt at computing the hashcode of DexClassAndMethod");
   }
 
-  public boolean hasResult() {
-    return this != NO_RESULT;
+  public DexClass getHolder() {
+    return holder;
   }
 
-  public boolean hasNoResult() {
-    return this == NO_RESULT;
+  public DexEncodedMethod getMethod() {
+    return method;
+  }
+
+  public boolean isProgramMethod() {
+    return false;
+  }
+
+  public ProgramMethod asProgramMethod() {
+    return null;
   }
 }
diff --git a/src/main/java/com/android/tools/r8/graph/ProgramMethod.java b/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
index 8a68ee5..4924d0c 100644
--- a/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
@@ -4,9 +4,26 @@
 package com.android.tools.r8.graph;
 
 /** Type representing a method definition in the programs compilation unit and its holder. */
-public final class ProgramMethod extends DexClassAndMethod<DexProgramClass> {
+public final class ProgramMethod extends DexClassAndMethod {
 
   public ProgramMethod(DexProgramClass holder, DexEncodedMethod method) {
     super(holder, method);
   }
+
+  @Override
+  public boolean isProgramMethod() {
+    return true;
+  }
+
+  @Override
+  public ProgramMethod asProgramMethod() {
+    return this;
+  }
+
+  @Override
+  public DexProgramClass getHolder() {
+    DexClass holder = super.getHolder();
+    assert holder.isProgramClass();
+    return holder.asProgramClass();
+  }
 }
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 1f5c91b..feffac7 100644
--- a/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
+++ b/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
@@ -86,7 +86,7 @@
     return lookupVirtualDispatchTargets(context, appView, appView.appInfo());
   }
 
-  public abstract DexClassAndMethod<?> lookupVirtualDispatchTarget(
+  public abstract DexClassAndMethod lookupVirtualDispatchTarget(
       DexProgramClass dynamicInstance, AppView<? extends AppInfoWithClassHierarchy> appView);
 
   /** Result for a resolution that succeeds with a known declaration/definition. */
@@ -356,10 +356,10 @@
       instantiatedInfo.forEachInstantiatedSubType(
           resolvedHolder.type,
           subClass -> {
-            DexClassAndMethod<?> dexClassAndMethod = lookupVirtualDispatchTarget(subClass, appView);
-            if (dexClassAndMethod.hasResult()) {
+            DexClassAndMethod dexClassAndMethod = lookupVirtualDispatchTarget(subClass, appView);
+            if (dexClassAndMethod != null) {
               addVirtualDispatchTarget(
-                  dexClassAndMethod.method, resolvedHolder.isInterface(), result);
+                  dexClassAndMethod.getMethod(), resolvedHolder.isInterface(), result);
             }
           },
           dexCallSite -> {
@@ -416,7 +416,7 @@
      * we have an object ref on the stack.
      */
     @Override
-    public DexClassAndMethod<?> lookupVirtualDispatchTarget(
+    public DexClassAndMethod lookupVirtualDispatchTarget(
         DexProgramClass dynamicInstance, AppView<? extends AppInfoWithClassHierarchy> appView) {
       // TODO(b/148591377): Enable this assertion.
       // The dynamic type cannot be an interface.
@@ -434,20 +434,20 @@
         if (candidate == null || candidate == DexEncodedMethod.SENTINEL) {
           // We cannot find a target above the resolved method.
           if (current.type == overrideTarget.method.holder) {
-            return DexClassAndMethod.createNoResult();
+            return null;
           }
           current = current.superType == null ? null : appView.definitionFor(current.superType);
           continue;
         }
-        return DexClassAndMethod.createResult(current, candidate);
+        return DexClassAndMethod.create(current, candidate);
       }
       // TODO(b/149557233): Enable assertion.
       // assert resolvedHolder.isInterface();
       DexEncodedMethod maximalSpecific =
           lookupMaximallySpecificDispatchTarget(dynamicInstance, appView);
       return maximalSpecific == null
-          ? DexClassAndMethod.createNoResult()
-          : DexClassAndMethod.createResult(
+          ? null
+          : DexClassAndMethod.create(
               appView.definitionFor(maximalSpecific.method.holder), maximalSpecific);
     }
 
@@ -555,9 +555,9 @@
     }
 
     @Override
-    public DexClassAndMethod<?> lookupVirtualDispatchTarget(
+    public DexClassAndMethod lookupVirtualDispatchTarget(
         DexProgramClass dynamicInstance, AppView<? extends AppInfoWithClassHierarchy> appView) {
-      return DexClassAndMethod.createNoResult();
+      return null;
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
index fae9325..0831e6d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -592,9 +592,9 @@
     @Override
     DexEncodedMethod ensureAccessibility(boolean allowMethodModification) {
       // We already found the static method to be called, just relax its accessibility.
-      target.method.accessFlags.unsetPrivate();
-      if (target.holder.isInterface()) {
-        target.method.accessFlags.setPublic();
+      target.getMethod().accessFlags.unsetPrivate();
+      if (target.getHolder().isInterface()) {
+        target.getMethod().accessFlags.setPublic();
       }
       return null;
     }
diff --git a/src/main/java/com/android/tools/r8/shaking/DefaultEnqueuerUseRegistry.java b/src/main/java/com/android/tools/r8/shaking/DefaultEnqueuerUseRegistry.java
index f05d068..dfcee69 100644
--- a/src/main/java/com/android/tools/r8/shaking/DefaultEnqueuerUseRegistry.java
+++ b/src/main/java/com/android/tools/r8/shaking/DefaultEnqueuerUseRegistry.java
@@ -32,11 +32,11 @@
   }
 
   public DexProgramClass getContextHolder() {
-    return context.holder;
+    return context.getHolder();
   }
 
   public DexEncodedMethod getContextMethod() {
-    return context.method;
+    return context.getMethod();
   }
 
   @Override
@@ -66,12 +66,12 @@
 
   @Override
   public boolean registerInstanceFieldWrite(DexField field) {
-    return enqueuer.traceInstanceFieldWrite(field, context.method);
+    return enqueuer.traceInstanceFieldWrite(field, context.getMethod());
   }
 
   @Override
   public boolean registerInstanceFieldRead(DexField field) {
-    return enqueuer.traceInstanceFieldRead(field, context.method);
+    return enqueuer.traceInstanceFieldRead(field, context.getMethod());
   }
 
   @Override
@@ -81,33 +81,33 @@
 
   @Override
   public boolean registerStaticFieldRead(DexField field) {
-    return enqueuer.traceStaticFieldRead(field, context.method);
+    return enqueuer.traceStaticFieldRead(field, context.getMethod());
   }
 
   @Override
   public boolean registerStaticFieldWrite(DexField field) {
-    return enqueuer.traceStaticFieldWrite(field, context.method);
+    return enqueuer.traceStaticFieldWrite(field, context.getMethod());
   }
 
   @Override
   public boolean registerConstClass(DexType type) {
-    return enqueuer.traceConstClass(type, context.method);
+    return enqueuer.traceConstClass(type, context.getMethod());
   }
 
   @Override
   public boolean registerCheckCast(DexType type) {
-    return enqueuer.traceCheckCast(type, context.method);
+    return enqueuer.traceCheckCast(type, context.getMethod());
   }
 
   @Override
   public boolean registerTypeReference(DexType type) {
-    return enqueuer.traceTypeReference(type, context.method);
+    return enqueuer.traceTypeReference(type, context.getMethod());
   }
 
   @Override
   public void registerMethodHandle(DexMethodHandle methodHandle, MethodHandleUse use) {
     super.registerMethodHandle(methodHandle, use);
-    enqueuer.traceMethodHandle(methodHandle, use, context.method);
+    enqueuer.traceMethodHandle(methodHandle, use, context.getMethod());
   }
 
   @Override
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 ba98418..a7bb64b 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -639,13 +639,14 @@
       bootstrapMethods.add(callSite.bootstrapMethod.asMethod());
     }
 
-    LambdaDescriptor descriptor = LambdaDescriptor.tryInfer(callSite, appInfo, context.holder);
+    DexProgramClass contextHolder = context.getHolder();
+    LambdaDescriptor descriptor = LambdaDescriptor.tryInfer(callSite, appInfo, contextHolder);
     if (descriptor == null) {
       if (!appInfo.isStringConcat(callSite.bootstrapMethod)) {
         if (options.reporter != null) {
           Diagnostic message =
               new StringDiagnostic(
-                  "Unknown bootstrap method " + callSite.bootstrapMethod, context.holder.origin);
+                  "Unknown bootstrap method " + callSite.bootstrapMethod, contextHolder.origin);
           options.reporter.warning(message);
         }
       }
@@ -654,22 +655,23 @@
       return;
     }
 
+    DexEncodedMethod contextMethod = context.getMethod();
     for (DexType lambdaInstantiatedInterface : descriptor.interfaces) {
-      markLambdaInstantiated(lambdaInstantiatedInterface, context.method);
+      markLambdaInstantiated(lambdaInstantiatedInterface, contextMethod);
     }
 
     if (lambdaRewriter != null) {
-      assert context.method.getCode().isCfCode() : "Unexpected input type with lambdas";
-      CfCode code = context.method.getCode().asCfCode();
+      assert contextMethod.getCode().isCfCode() : "Unexpected input type with lambdas";
+      CfCode code = contextMethod.getCode().asCfCode();
       if (code != null) {
         LambdaClass lambdaClass =
-            lambdaRewriter.getOrCreateLambdaClass(descriptor, context.method.method.holder);
+            lambdaRewriter.getOrCreateLambdaClass(descriptor, contextMethod.method.holder);
         lambdaClasses.put(lambdaClass.type, lambdaClass);
         lambdaCallSites
-            .computeIfAbsent(context.method, k -> new IdentityHashMap<>())
+            .computeIfAbsent(contextMethod, k -> new IdentityHashMap<>())
             .put(callSite, lambdaClass);
         if (lambdaClass.descriptor.interfaces.contains(appView.dexItemFactory().serializableType)) {
-          classesWithSerializableLambdas.add(context.holder);
+          classesWithSerializableLambdas.add(contextHolder);
         }
       }
       if (descriptor.delegatesToLambdaImplMethod()) {
@@ -797,8 +799,8 @@
   }
 
   boolean traceInvokeDirect(DexMethod invokedMethod, ProgramMethod context) {
-    DexProgramClass currentHolder = context.holder;
-    DexEncodedMethod currentMethod = context.method;
+    DexProgramClass currentHolder = context.getHolder();
+    DexEncodedMethod currentMethod = context.getMethod();
     boolean skipTracing =
         registerDeferredActionForDeadProtoBuilder(
             invokedMethod.holder,
@@ -830,12 +832,12 @@
 
   boolean traceInvokeDirectFromLambda(DexMethod invokedMethod, ProgramMethod context) {
     return traceInvokeDirect(
-        invokedMethod, context, KeepReason.invokedFromLambdaCreatedIn(context.method));
+        invokedMethod, context, KeepReason.invokedFromLambdaCreatedIn(context.getMethod()));
   }
 
   private boolean traceInvokeDirect(
       DexMethod invokedMethod, ProgramMethod context, KeepReason reason) {
-    DexEncodedMethod currentMethod = context.method;
+    DexEncodedMethod currentMethod = context.getMethod();
     if (!registerMethodWithTargetAndContext(directInvokes, invokedMethod, currentMethod)) {
       return false;
     }
@@ -848,18 +850,17 @@
   }
 
   boolean traceInvokeInterface(DexMethod invokedMethod, ProgramMethod context) {
-    return traceInvokeInterface(
-        invokedMethod, context, KeepReason.invokedFrom(context.holder, context.method));
+    return traceInvokeInterface(invokedMethod, context, KeepReason.invokedFrom(context));
   }
 
   boolean traceInvokeInterfaceFromLambda(DexMethod invokedMethod, ProgramMethod context) {
     return traceInvokeInterface(
-        invokedMethod, context, KeepReason.invokedFromLambdaCreatedIn(context.method));
+        invokedMethod, context, KeepReason.invokedFromLambdaCreatedIn(context.getMethod()));
   }
 
   private boolean traceInvokeInterface(
       DexMethod method, ProgramMethod context, KeepReason keepReason) {
-    DexEncodedMethod currentMethod = context.method;
+    DexEncodedMethod currentMethod = context.getMethod();
     if (!registerMethodWithTargetAndContext(interfaceInvokes, method, currentMethod)) {
       return false;
     }
@@ -872,18 +873,17 @@
   }
 
   boolean traceInvokeStatic(DexMethod invokedMethod, ProgramMethod context) {
-    return traceInvokeStatic(
-        invokedMethod, context, KeepReason.invokedFrom(context.holder, context.method));
+    return traceInvokeStatic(invokedMethod, context, KeepReason.invokedFrom(context));
   }
 
   boolean traceInvokeStaticFromLambda(DexMethod invokedMethod, ProgramMethod context) {
     return traceInvokeStatic(
-        invokedMethod, context, KeepReason.invokedFromLambdaCreatedIn(context.method));
+        invokedMethod, context, KeepReason.invokedFromLambdaCreatedIn(context.getMethod()));
   }
 
   private boolean traceInvokeStatic(
       DexMethod invokedMethod, ProgramMethod context, KeepReason reason) {
-    DexEncodedMethod currentMethod = context.method;
+    DexEncodedMethod currentMethod = context.getMethod();
     DexItemFactory dexItemFactory = appView.dexItemFactory();
     if (dexItemFactory.classMethods.isReflectiveClassLookup(invokedMethod)
         || dexItemFactory.atomicFieldUpdaterMethods.isFieldUpdater(invokedMethod)) {
@@ -915,8 +915,7 @@
   }
 
   boolean traceInvokeSuper(DexMethod invokedMethod, ProgramMethod context) {
-    DexProgramClass currentHolder = context.holder;
-    DexEncodedMethod currentMethod = context.method;
+    DexEncodedMethod currentMethod = context.getMethod();
     // We have to revisit super invokes based on the context they are found in. The same
     // method descriptor will hit different targets, depending on the context it is used in.
     DexMethod actualTarget = getInvokeSuperTarget(invokedMethod, currentMethod);
@@ -932,27 +931,26 @@
   }
 
   boolean traceInvokeVirtual(DexMethod invokedMethod, ProgramMethod context) {
-    return traceInvokeVirtual(
-        invokedMethod, context, KeepReason.invokedFrom(context.holder, context.method));
+    return traceInvokeVirtual(invokedMethod, context, KeepReason.invokedFrom(context));
   }
 
   boolean traceInvokeVirtualFromLambda(DexMethod invokedMethod, ProgramMethod context) {
     return traceInvokeVirtual(
-        invokedMethod, context, KeepReason.invokedFromLambdaCreatedIn(context.method));
+        invokedMethod, context, KeepReason.invokedFromLambdaCreatedIn(context.getMethod()));
   }
 
   private boolean traceInvokeVirtual(
       DexMethod invokedMethod, ProgramMethod context, KeepReason reason) {
     if (invokedMethod == appView.dexItemFactory().classMethods.newInstance
         || invokedMethod == appView.dexItemFactory().constructorMethods.newInstance) {
-      pendingReflectiveUses.add(context.method);
+      pendingReflectiveUses.add(context.getMethod());
     } else if (appView.dexItemFactory().classMethods.isReflectiveMemberLookup(invokedMethod)) {
       // Implicitly add -identifiernamestring rule for the Java reflection in use.
       identifierNameStrings.add(invokedMethod);
       // Revisit the current method to implicitly add -keep rule for items with reflective access.
-      pendingReflectiveUses.add(context.method);
+      pendingReflectiveUses.add(context.getMethod());
     }
-    if (!registerMethodWithTargetAndContext(virtualInvokes, invokedMethod, context.method)) {
+    if (!registerMethodWithTargetAndContext(virtualInvokes, invokedMethod, context.getMethod())) {
       return false;
     }
     if (Log.ENABLED) {
@@ -964,7 +962,7 @@
   }
 
   boolean traceNewInstance(DexType type, ProgramMethod context) {
-    DexEncodedMethod currentMethod = context.method;
+    DexEncodedMethod currentMethod = context.getMethod();
     boolean skipTracing =
         registerDeferredActionForDeadProtoBuilder(
             type, currentMethod, () -> workList.enqueueTraceNewInstanceAction(type, context));
@@ -984,7 +982,7 @@
         type,
         context,
         InstantiationReason.LAMBDA,
-        KeepReason.invokedFromLambdaCreatedIn(context.method));
+        KeepReason.invokedFromLambdaCreatedIn(context.getMethod()));
   }
 
   private boolean traceNewInstance(
@@ -992,7 +990,7 @@
       ProgramMethod context,
       InstantiationReason instantiationReason,
       KeepReason keepReason) {
-    DexEncodedMethod currentMethod = context.method;
+    DexEncodedMethod currentMethod = context.getMethod();
     DexProgramClass clazz = getProgramClassOrNull(type);
     if (clazz != null) {
       if (clazz.isAnnotation() || clazz.isInterface()) {
@@ -2154,7 +2152,7 @@
     if (contextOrNull != null
         && !resolution.isUnresolved()
         && !AccessControl.isMethodAccessible(
-            resolution.method, holder, contextOrNull.holder, appInfo)) {
+            resolution.method, holder, contextOrNull.getHolder(), appInfo)) {
       // Not accessible from this context, so this call will cause a runtime exception.
       // Note that the resolution is not cached, as another call context may be valid.
       return;
@@ -2174,7 +2172,7 @@
     assert resolution.holder.isProgramClass();
 
     assert interfaceInvoke == holder.isInterface();
-    DexProgramClass context = contextOrNull == null ? null : contextOrNull.holder;
+    DexProgramClass context = contextOrNull == null ? null : contextOrNull.getHolder();
     LookupResult lookupResult =
         // TODO(b/140214802): Call on the resolution once proper resolution and lookup is resolved.
         new SingleResolutionResult(holder, resolution.holder, resolution.method)
@@ -2432,10 +2430,11 @@
     assert fieldAccessInfoCollection.verifyMappingIsOneToOne();
 
     for (ProgramMethod bridge : syntheticInterfaceMethodBridges.values()) {
-      appView.appInfo().invalidateTypeCacheFor(bridge.holder.type);
-      bridge.holder.appendVirtualMethod(bridge.method);
-      targetedMethods.add(bridge.method, graphReporter.fakeReportShouldNotBeUsed());
-      liveMethods.add(bridge.holder, bridge.method, graphReporter.fakeReportShouldNotBeUsed());
+      appView.appInfo().invalidateTypeCacheFor(bridge.getHolder().type);
+      bridge.getHolder().appendVirtualMethod(bridge.getMethod());
+      targetedMethods.add(bridge.getMethod(), graphReporter.fakeReportShouldNotBeUsed());
+      liveMethods.add(
+          bridge.getHolder(), bridge.getMethod(), graphReporter.fakeReportShouldNotBeUsed());
     }
 
     // Ensure references from various root set collections.
@@ -2866,25 +2865,27 @@
       InterfaceMethodSyntheticBridgeAction action, RootSetBuilder builder) {
     ProgramMethod methodToKeep = action.getMethodToKeep();
     ProgramMethod singleTarget = action.getSingleTarget();
-    if (rootSet.noShrinking.containsKey(singleTarget.method.method)) {
+    DexEncodedMethod singleTargetMethod = singleTarget.getMethod();
+    if (rootSet.noShrinking.containsKey(singleTargetMethod.method)) {
       return;
     }
     if (methodToKeep != singleTarget) {
-      assert null == methodToKeep.holder.lookupMethod(methodToKeep.method.method);
+      assert null == methodToKeep.getHolder().lookupMethod(methodToKeep.getMethod().method);
       ProgramMethod old =
-          syntheticInterfaceMethodBridges.put(methodToKeep.method.method, methodToKeep);
+          syntheticInterfaceMethodBridges.put(methodToKeep.getMethod().method, methodToKeep);
       if (old == null) {
-        if (singleTarget.method.isLibraryMethodOverride().isTrue()) {
-          methodToKeep.method.setLibraryMethodOverride(OptionalBool.TRUE);
+        if (singleTargetMethod.isLibraryMethodOverride().isTrue()) {
+          methodToKeep.getMethod().setLibraryMethodOverride(OptionalBool.TRUE);
         }
-        assert singleTarget.holder.isInterface();
+        DexProgramClass singleTargetHolder = singleTarget.getHolder();
+        assert singleTargetHolder.isInterface();
         markVirtualMethodAsReachable(
-            singleTarget.method.method,
-            singleTarget.holder.isInterface(),
+            singleTargetMethod.method,
+            singleTargetHolder.isInterface(),
             null,
             graphReporter.fakeReportShouldNotBeUsed());
         enqueueMarkMethodLiveAction(
-            singleTarget.holder, singleTarget.method, graphReporter.fakeReportShouldNotBeUsed());
+            singleTargetHolder, singleTargetMethod, graphReporter.fakeReportShouldNotBeUsed());
       }
     }
     action.getAction().accept(builder);
diff --git a/src/main/java/com/android/tools/r8/shaking/KeepReason.java b/src/main/java/com/android/tools/r8/shaking/KeepReason.java
index 680c0b5..cc86522 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepReason.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepReason.java
@@ -12,6 +12,7 @@
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
 
 // TODO(herhut): Canonicalize reason objects.
 public abstract class KeepReason {
@@ -40,6 +41,10 @@
     return new InvokedFrom(holder, method);
   }
 
+  public static KeepReason invokedFrom(ProgramMethod context) {
+    return invokedFrom(context.getHolder(), context.getMethod());
+  }
+
   public static KeepReason invokedFromLambdaCreatedIn(DexEncodedMethod method) {
     return new InvokedFromLambdaCreatedIn(method);
   }
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 cdc5782..7d93686 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -557,9 +557,10 @@
               resolutionResult.getResolvedHolder().asProgramClass(),
               resolutionResult.getResolvedMethod());
       ProgramMethod methodToKeep =
-          canInsertForwardingMethod(originalClazz, resolutionMethod.method)
+          canInsertForwardingMethod(originalClazz, resolutionMethod.getMethod())
               ? new ProgramMethod(
-                  originalClazz, resolutionMethod.method.toForwardingMethod(originalClazz, appView))
+                  originalClazz,
+                  resolutionMethod.getMethod().toForwardingMethod(originalClazz, appView))
               : resolutionMethod;
 
       delayedRootSetActionItems.add(
@@ -576,9 +577,9 @@
                       rule);
                 }
                 DexDefinition precondition =
-                    testAndGetPrecondition(methodToKeep.method, preconditionSupplier);
+                    testAndGetPrecondition(methodToKeep.getMethod(), preconditionSupplier);
                 rootSetBuilder.addItemToSets(
-                    methodToKeep.method, context, rule, precondition, ifRule);
+                    methodToKeep.getMethod(), context, rule, precondition, ifRule);
               }));
     }
   }