Revert "Towards raising a diagnostic for package-private cross-split references"

This reverts commit 450399f4e6f630e5a57ef69f5bce56c63dca8e9b.


Revert "Suppress error prone warnings in split checker"

This reverts commit 475d350e3a8781c5a9a123566211ecfacad652c8.

Change-Id: Id77ee214c65d09d31074399f11f2d20bfd80ad31
diff --git a/src/main/java/com/android/tools/r8/features/IsolatedFeatureSplitsChecker.java b/src/main/java/com/android/tools/r8/features/IsolatedFeatureSplitsChecker.java
deleted file mode 100644
index ee3e64f..0000000
--- a/src/main/java/com/android/tools/r8/features/IsolatedFeatureSplitsChecker.java
+++ /dev/null
@@ -1,174 +0,0 @@
-// 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.features;
-
-import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
-import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.FieldResolutionResult;
-import com.android.tools.r8.graph.FieldResolutionResult.SingleFieldResolutionResult;
-import com.android.tools.r8.graph.MethodResolutionResult;
-import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.graph.analysis.EnqueuerFieldAccessAnalysis;
-import com.android.tools.r8.graph.analysis.EnqueuerInvokeAnalysis;
-import com.android.tools.r8.graph.analysis.EnqueuerTypeAccessAnalysis;
-import com.android.tools.r8.shaking.Enqueuer;
-import com.android.tools.r8.shaking.EnqueuerWorklist;
-import com.android.tools.r8.utils.InternalOptions;
-
-// TODO(b/300247439): Also trace types referenced from new-array instructions, call sites, etc.
-public class IsolatedFeatureSplitsChecker
-    implements EnqueuerFieldAccessAnalysis, EnqueuerInvokeAnalysis, EnqueuerTypeAccessAnalysis {
-
-  @SuppressWarnings("UnusedVariable")
-  private final AppView<? extends AppInfoWithClassHierarchy> appView;
-
-  @SuppressWarnings("UnusedVariable")
-  private final Enqueuer enqueuer;
-
-  private IsolatedFeatureSplitsChecker(
-      AppView<? extends AppInfoWithClassHierarchy> appView, Enqueuer enqueuer) {
-    this.appView = appView;
-    this.enqueuer = enqueuer;
-  }
-
-  public static void register(
-      AppView<? extends AppInfoWithClassHierarchy> appView, Enqueuer enqueuer) {
-    if (enabled(appView, enqueuer)) {
-      IsolatedFeatureSplitsChecker checker = new IsolatedFeatureSplitsChecker(appView, enqueuer);
-      enqueuer
-          .registerFieldAccessAnalysis(checker)
-          .registerInvokeAnalysis(checker)
-          .registerTypeAccessAnalysis(checker);
-    }
-  }
-
-  private static boolean enabled(
-      AppView<? extends AppInfoWithClassHierarchy> appView, Enqueuer enqueuer) {
-    InternalOptions options = appView.options();
-    return options.hasFeatureSplitConfiguration()
-        && options.getFeatureSplitConfiguration().isIsolatedSplitsEnabled()
-        && enqueuer.getMode().isInitialTreeShaking();
-  }
-
-  @SuppressWarnings("UnusedVariable")
-  private void traceFieldAccess(FieldResolutionResult resolutionResult, ProgramMethod context) {
-    // TODO(b/300247439): Check access.
-  }
-
-  @SuppressWarnings("UnusedVariable")
-  private void traceMethodInvoke(MethodResolutionResult resolutionResult, ProgramMethod context) {
-    // TODO(b/300247439): Check access.
-  }
-
-  @SuppressWarnings("UnusedVariable")
-  private void traceTypeAccess(DexClass clazz, ProgramMethod context) {
-    // TODO(b/300247439): Check access.
-  }
-
-  // Field accesses.
-
-  @Override
-  public void traceInstanceFieldRead(
-      DexField field,
-      FieldResolutionResult resolutionResult,
-      ProgramMethod context,
-      EnqueuerWorklist worklist) {
-    traceFieldAccess(resolutionResult, context);
-  }
-
-  @Override
-  public void traceInstanceFieldWrite(
-      DexField field,
-      FieldResolutionResult resolutionResult,
-      ProgramMethod context,
-      EnqueuerWorklist worklist) {
-    traceFieldAccess(resolutionResult, context);
-  }
-
-  @Override
-  public void traceStaticFieldRead(
-      DexField field,
-      SingleFieldResolutionResult<?> resolutionResult,
-      ProgramMethod context,
-      EnqueuerWorklist worklist) {
-    traceFieldAccess(resolutionResult, context);
-  }
-
-  @Override
-  public void traceStaticFieldWrite(
-      DexField field,
-      FieldResolutionResult resolutionResult,
-      ProgramMethod context,
-      EnqueuerWorklist worklist) {
-    traceFieldAccess(resolutionResult, context);
-  }
-
-  // Method invokes.
-
-  @Override
-  public void traceInvokeStatic(
-      DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
-    traceMethodInvoke(resolutionResult, context);
-  }
-
-  @Override
-  public void traceInvokeDirect(
-      DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
-    traceMethodInvoke(resolutionResult, context);
-  }
-
-  @Override
-  public void traceInvokeInterface(
-      DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
-    traceMethodInvoke(resolutionResult, context);
-  }
-
-  @Override
-  public void traceInvokeSuper(
-      DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
-    traceMethodInvoke(resolutionResult, context);
-  }
-
-  @Override
-  public void traceInvokeVirtual(
-      DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
-    traceMethodInvoke(resolutionResult, context);
-  }
-
-  // Type accesses.
-
-  @Override
-  public void traceCheckCast(DexType type, DexClass clazz, ProgramMethod context) {
-    traceTypeAccess(clazz, context);
-  }
-
-  @Override
-  public void traceSafeCheckCast(DexType type, DexClass clazz, ProgramMethod context) {
-    traceTypeAccess(clazz, context);
-  }
-
-  @Override
-  public void traceConstClass(DexType type, DexClass clazz, ProgramMethod context) {
-    traceTypeAccess(clazz, context);
-  }
-
-  @Override
-  public void traceExceptionGuard(DexType type, DexClass clazz, ProgramMethod context) {
-    traceTypeAccess(clazz, context);
-  }
-
-  @Override
-  public void traceInstanceOf(DexType type, DexClass clazz, ProgramMethod context) {
-    traceTypeAccess(clazz, context);
-  }
-
-  @Override
-  public void traceNewInstance(DexType type, DexClass clazz, ProgramMethod context) {
-    traceTypeAccess(clazz, context);
-  }
-}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerCheckCastAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerCheckCastAnalysis.java
index 1ff19a6..ad0dcbf 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerCheckCastAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerCheckCastAnalysis.java
@@ -4,13 +4,12 @@
 
 package com.android.tools.r8.graph.analysis;
 
-import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.ProgramMethod;
 
 public interface EnqueuerCheckCastAnalysis {
 
-  void traceCheckCast(DexType type, DexClass clazz, ProgramMethod context);
+  void traceCheckCast(DexType type, ProgramMethod context);
 
-  void traceSafeCheckCast(DexType type, DexClass clazz, ProgramMethod context);
+  void traceSafeCheckCast(DexType type, ProgramMethod context);
 }
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerConstClassAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerConstClassAnalysis.java
deleted file mode 100644
index 61f127a..0000000
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerConstClassAnalysis.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// 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.analysis;
-
-import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.ProgramMethod;
-
-public interface EnqueuerConstClassAnalysis {
-
-  void traceConstClass(DexType type, DexClass clazz, ProgramMethod context);
-}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerExceptionGuardAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerExceptionGuardAnalysis.java
index 752e4a5..1bf392e 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerExceptionGuardAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerExceptionGuardAnalysis.java
@@ -4,10 +4,9 @@
 
 package com.android.tools.r8.graph.analysis;
 
-import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.ProgramMethod;
 
 public interface EnqueuerExceptionGuardAnalysis {
-  void traceExceptionGuard(DexType guard, DexClass clazz, ProgramMethod context);
+  void traceExceptionGuard(DexType guard, ProgramMethod context);
 }
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerFieldAccessAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerFieldAccessAnalysis.java
index 69eb560..0642216 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerFieldAccessAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerFieldAccessAnalysis.java
@@ -18,24 +18,28 @@
       FieldResolutionResult resolutionResult,
       ProgramMethod context,
       EnqueuerWorklist worklist) {}
+  ;
 
   default void traceInstanceFieldWrite(
       DexField field,
       FieldResolutionResult resolutionResult,
       ProgramMethod context,
       EnqueuerWorklist worklist) {}
+  ;
 
   default void traceStaticFieldRead(
       DexField field,
       SingleFieldResolutionResult<?> resolutionResult,
       ProgramMethod context,
       EnqueuerWorklist worklist) {}
+  ;
 
   default void traceStaticFieldWrite(
       DexField field,
       FieldResolutionResult resolutionResult,
       ProgramMethod context,
       EnqueuerWorklist worklist) {}
+  ;
 
   /**
    * Called when the Enqueuer has reached the final fixpoint. Each analysis may use this callback to
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInstanceOfAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInstanceOfAnalysis.java
index 485a311..abda4d1 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInstanceOfAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInstanceOfAnalysis.java
@@ -4,10 +4,9 @@
 
 package com.android.tools.r8.graph.analysis;
 
-import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.ProgramMethod;
 
 public interface EnqueuerInstanceOfAnalysis {
-  void traceInstanceOf(DexType type, DexClass clazz, ProgramMethod context);
+  void traceInstanceOf(DexType type, ProgramMethod context);
 }
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInvokeAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInvokeAnalysis.java
index d2ca27d..d0a39b3 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInvokeAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInvokeAnalysis.java
@@ -4,7 +4,6 @@
 package com.android.tools.r8.graph.analysis;
 
 import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.MethodResolutionResult;
 import com.android.tools.r8.graph.ProgramMethod;
 
 public interface EnqueuerInvokeAnalysis {
@@ -13,18 +12,13 @@
    * Each traceInvokeXX method is called when a corresponding invoke is found while tracing a live
    * method.
    */
-  void traceInvokeStatic(
-      DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context);
+  void traceInvokeStatic(DexMethod invokedMethod, ProgramMethod context);
 
-  void traceInvokeDirect(
-      DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context);
+  void traceInvokeDirect(DexMethod invokedMethod, ProgramMethod context);
 
-  void traceInvokeInterface(
-      DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context);
+  void traceInvokeInterface(DexMethod invokedMethod, ProgramMethod context);
 
-  void traceInvokeSuper(
-      DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context);
+  void traceInvokeSuper(DexMethod invokedMethod, ProgramMethod context);
 
-  void traceInvokeVirtual(
-      DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context);
+  void traceInvokeVirtual(DexMethod invokedMethod, ProgramMethod context);
 }
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerNewInstanceAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerNewInstanceAnalysis.java
deleted file mode 100644
index 880c91a..0000000
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerNewInstanceAnalysis.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// 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.analysis;
-
-import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.ProgramMethod;
-
-public interface EnqueuerNewInstanceAnalysis {
-
-  void traceNewInstance(DexType type, DexClass clazz, ProgramMethod context);
-}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerTypeAccessAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerTypeAccessAnalysis.java
deleted file mode 100644
index 3d44ef1..0000000
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerTypeAccessAnalysis.java
+++ /dev/null
@@ -1,11 +0,0 @@
-// 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.analysis;
-
-public interface EnqueuerTypeAccessAnalysis
-    extends EnqueuerCheckCastAnalysis,
-        EnqueuerConstClassAnalysis,
-        EnqueuerExceptionGuardAnalysis,
-        EnqueuerInstanceOfAnalysis,
-        EnqueuerNewInstanceAnalysis {}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/InvokeVirtualToInterfaceVerifyErrorWorkaround.java b/src/main/java/com/android/tools/r8/graph/analysis/InvokeVirtualToInterfaceVerifyErrorWorkaround.java
index 70fca76..94bf7ce 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/InvokeVirtualToInterfaceVerifyErrorWorkaround.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/InvokeVirtualToInterfaceVerifyErrorWorkaround.java
@@ -8,7 +8,6 @@
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.MethodResolutionResult;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.shaking.Enqueuer;
 import com.android.tools.r8.shaking.KeepInfo.Joiner;
@@ -54,8 +53,7 @@
   }
 
   @Override
-  public void traceInvokeVirtual(
-      DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
+  public void traceInvokeVirtual(DexMethod invokedMethod, ProgramMethod context) {
     if (isInterfaceInSomeApiLevel(invokedMethod.getHolderType())) {
       enqueuer.getKeepInfo().joinMethod(context, Joiner::disallowOptimization);
     }
@@ -71,26 +69,22 @@
   }
 
   @Override
-  public void traceInvokeDirect(
-      DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
+  public void traceInvokeDirect(DexMethod invokedMethod, ProgramMethod context) {
     // Intentionally empty.
   }
 
   @Override
-  public void traceInvokeInterface(
-      DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
+  public void traceInvokeInterface(DexMethod invokedMethod, ProgramMethod context) {
     // Intentionally empty.
   }
 
   @Override
-  public void traceInvokeStatic(
-      DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
+  public void traceInvokeStatic(DexMethod invokedMethod, ProgramMethod context) {
     // Intentionally empty.
   }
 
   @Override
-  public void traceInvokeSuper(
-      DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
+  public void traceInvokeSuper(DexMethod invokedMethod, ProgramMethod context) {
     // Intentionally empty.
   }
 }
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 93aa9fb..ea7cbf5 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -27,7 +27,6 @@
 import com.android.tools.r8.errors.InterfaceDesugarMissingTypeDiagnostic;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
-import com.android.tools.r8.features.IsolatedFeatureSplitsChecker;
 import com.android.tools.r8.graph.AccessControl;
 import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
@@ -91,13 +90,10 @@
 import com.android.tools.r8.graph.analysis.ApiModelAnalysis;
 import com.android.tools.r8.graph.analysis.EnqueuerAnalysis;
 import com.android.tools.r8.graph.analysis.EnqueuerCheckCastAnalysis;
-import com.android.tools.r8.graph.analysis.EnqueuerConstClassAnalysis;
 import com.android.tools.r8.graph.analysis.EnqueuerExceptionGuardAnalysis;
 import com.android.tools.r8.graph.analysis.EnqueuerFieldAccessAnalysis;
 import com.android.tools.r8.graph.analysis.EnqueuerInstanceOfAnalysis;
 import com.android.tools.r8.graph.analysis.EnqueuerInvokeAnalysis;
-import com.android.tools.r8.graph.analysis.EnqueuerNewInstanceAnalysis;
-import com.android.tools.r8.graph.analysis.EnqueuerTypeAccessAnalysis;
 import com.android.tools.r8.graph.analysis.GetArrayOfMissingTypeVerifyErrorWorkaround;
 import com.android.tools.r8.graph.analysis.InvokeVirtualToInterfaceVerifyErrorWorkaround;
 import com.android.tools.r8.graph.analysis.ResourceAccessAnalysis;
@@ -260,8 +256,6 @@
   private final Set<EnqueuerInstanceOfAnalysis> instanceOfAnalyses = new LinkedHashSet<>();
   private final Set<EnqueuerExceptionGuardAnalysis> exceptionGuardAnalyses = new LinkedHashSet<>();
   private final Set<EnqueuerCheckCastAnalysis> checkCastAnalyses = new LinkedHashSet<>();
-  private final Set<EnqueuerConstClassAnalysis> constClassAnalyses = new LinkedHashSet<>();
-  private final Set<EnqueuerNewInstanceAnalysis> newInstanceAnalyses = new LinkedHashSet<>();
 
   // Don't hold a direct pointer to app info (use appView).
   private AppInfoWithClassHierarchy appInfo;
@@ -514,7 +508,6 @@
       }
       appView.withGeneratedMessageLiteBuilderShrinker(
           shrinker -> registerAnalysis(shrinker.createEnqueuerAnalysis()));
-      IsolatedFeatureSplitsChecker.register(appView, this);
       ResourceAccessAnalysis.register(appView, this);
     }
 
@@ -592,29 +585,11 @@
     return this;
   }
 
-  public Enqueuer registerConstClassAnalysis(EnqueuerConstClassAnalysis analysis) {
-    constClassAnalyses.add(analysis);
-    return this;
-  }
-
   public Enqueuer registerExceptionGuardAnalysis(EnqueuerExceptionGuardAnalysis analysis) {
     exceptionGuardAnalyses.add(analysis);
     return this;
   }
 
-  public Enqueuer registerNewInstanceAnalysis(EnqueuerNewInstanceAnalysis analysis) {
-    newInstanceAnalyses.add(analysis);
-    return this;
-  }
-
-  public Enqueuer registerTypeAccessAnalysis(EnqueuerTypeAccessAnalysis analysis) {
-    return registerCheckCastAnalysis(analysis)
-        .registerConstClassAnalysis(analysis)
-        .registerExceptionGuardAnalysis(analysis)
-        .registerInstanceOfAnalysis(analysis)
-        .registerNewInstanceAnalysis(analysis);
-  }
-
   public void setAnnotationRemoverBuilder(AnnotationRemover.Builder annotationRemoverBuilder) {
     this.annotationRemoverBuilder = annotationRemoverBuilder;
   }
@@ -1252,23 +1227,23 @@
   }
 
   void traceCheckCast(DexType type, ProgramMethod currentMethod, boolean ignoreCompatRules) {
-    DexClass clazz = internalTraceConstClassOrCheckCast(type, currentMethod, ignoreCompatRules);
-    checkCastAnalyses.forEach(analysis -> analysis.traceCheckCast(type, clazz, currentMethod));
+    checkCastAnalyses.forEach(analysis -> analysis.traceCheckCast(type, currentMethod));
+    internalTraceConstClassOrCheckCast(type, currentMethod, ignoreCompatRules);
   }
 
   void traceSafeCheckCast(DexType type, ProgramMethod currentMethod) {
-    DexClass clazz = internalTraceConstClassOrCheckCast(type, currentMethod, true);
-    checkCastAnalyses.forEach(analysis -> analysis.traceSafeCheckCast(type, clazz, currentMethod));
+    checkCastAnalyses.forEach(analysis -> analysis.traceSafeCheckCast(type, currentMethod));
+    internalTraceConstClassOrCheckCast(type, currentMethod, true);
   }
 
+  @SuppressWarnings("ReferenceEquality")
   void traceConstClass(
       DexType type,
       ProgramMethod currentMethod,
       ListIterator<? extends CfOrDexInstruction> iterator,
       boolean ignoreCompatRules) {
     handleLockCandidate(type, currentMethod, iterator);
-    DexClass clazz = internalTraceConstClassOrCheckCast(type, currentMethod, ignoreCompatRules);
-    constClassAnalyses.forEach(analysis -> analysis.traceConstClass(type, clazz, currentMethod));
+    internalTraceConstClassOrCheckCast(type, currentMethod, ignoreCompatRules);
   }
 
   private void handleLockCandidate(
@@ -1323,21 +1298,18 @@
     return result;
   }
 
-  private DexClass internalTraceConstClassOrCheckCast(
+  private void internalTraceConstClassOrCheckCast(
       DexType type, ProgramMethod currentMethod, boolean ignoreCompatRules) {
-    DexClass baseClass = resolveBaseType(type, currentMethod);
+    DexProgramClass baseClass = resolveBaseType(type, currentMethod);
     traceTypeReference(type, currentMethod);
     if (!forceProguardCompatibility || ignoreCompatRules) {
-      return baseClass;
+      return;
     }
-    if (baseClass != null && baseClass.isProgramClass()) {
+    if (baseClass != null) {
       // Don't require any constructor, see b/112386012.
-      DexProgramClass baseProgramClass = baseClass.asProgramClass();
       markClassAsInstantiatedWithCompatRule(
-          baseProgramClass,
-          () -> graphReporter.reportCompatInstantiated(baseProgramClass, currentMethod));
+          baseClass, () -> graphReporter.reportCompatInstantiated(baseClass, currentMethod));
     }
-    return baseClass;
   }
 
   void traceRecordFieldValues(DexField[] fields, ProgramMethod currentMethod) {
@@ -1429,16 +1401,14 @@
   }
 
   void traceInstanceOf(DexType type, ProgramMethod currentMethod) {
-    DexClass clazz = resolveBaseType(type, currentMethod);
+    instanceOfAnalyses.forEach(analysis -> analysis.traceInstanceOf(type, currentMethod));
+    resolveBaseType(type, currentMethod);
     traceTypeReference(type, currentMethod);
-    instanceOfAnalyses.forEach(analysis -> analysis.traceInstanceOf(type, clazz, currentMethod));
   }
 
-  void traceExceptionGuard(DexType type, ProgramMethod currentMethod) {
-    DexClass clazz = resolveBaseType(type, currentMethod);
-    traceTypeReference(type, currentMethod);
-    exceptionGuardAnalyses.forEach(
-        analysis -> analysis.traceExceptionGuard(type, clazz, currentMethod));
+  void traceExceptionGuard(DexType guard, ProgramMethod currentMethod) {
+    exceptionGuardAnalyses.forEach(analysis -> analysis.traceExceptionGuard(guard, currentMethod));
+    traceTypeReference(guard, currentMethod);
   }
 
   void traceInvokeDirect(DexMethod invokedMethod, ProgramMethod context) {
@@ -1479,10 +1449,8 @@
         methodAccessInfoCollection::registerInvokeDirectInContext, invokedMethod, context)) {
       return;
     }
-    MethodResolutionResult resolutionResult =
-        handleInvokeOfDirectTarget(invokedMethod, context, reason);
-    invokeAnalyses.forEach(
-        analysis -> analysis.traceInvokeDirect(invokedMethod, resolutionResult, context));
+    handleInvokeOfDirectTarget(invokedMethod, context, reason);
+    invokeAnalyses.forEach(analysis -> analysis.traceInvokeDirect(invokedMethod, context));
   }
 
   void traceInvokeInterface(DexMethod invokedMethod, ProgramMethod context) {
@@ -1499,8 +1467,8 @@
         methodAccessInfoCollection::registerInvokeInterfaceInContext, method, context)) {
       return;
     }
-    MethodResolutionResult result = markVirtualMethodAsReachable(method, true, context, keepReason);
-    invokeAnalyses.forEach(analysis -> analysis.traceInvokeInterface(method, result, context));
+    markVirtualMethodAsReachable(method, true, context, keepReason);
+    invokeAnalyses.forEach(analysis -> analysis.traceInvokeInterface(method, context));
   }
 
   void traceInvokeStatic(DexMethod invokedMethod, ProgramMethod context) {
@@ -1537,10 +1505,8 @@
         methodAccessInfoCollection::registerInvokeStaticInContext, invokedMethod, context)) {
       return;
     }
-    MethodResolutionResult resolutionResult =
-        handleInvokeOfStaticTarget(invokedMethod, context, reason);
-    invokeAnalyses.forEach(
-        analysis -> analysis.traceInvokeStatic(invokedMethod, resolutionResult, context));
+    handleInvokeOfStaticTarget(invokedMethod, context, reason);
+    invokeAnalyses.forEach(analysis -> analysis.traceInvokeStatic(invokedMethod, context));
   }
 
   void traceInvokeSuper(DexMethod invokedMethod, ProgramMethod context) {
@@ -1551,6 +1517,7 @@
       return;
     }
     worklist.enqueueMarkReachableSuperAction(invokedMethod, context);
+    invokeAnalyses.forEach(analysis -> analysis.traceInvokeSuper(invokedMethod, context));
   }
 
   void traceInvokeVirtual(DexMethod invokedMethod, ProgramMethod context) {
@@ -1577,10 +1544,8 @@
         methodAccessInfoCollection::registerInvokeVirtualInContext, invokedMethod, context)) {
       return;
     }
-    MethodResolutionResult resolutionResult =
-        markVirtualMethodAsReachable(invokedMethod, false, context, reason);
-    invokeAnalyses.forEach(
-        analysis -> analysis.traceInvokeVirtual(invokedMethod, resolutionResult, context));
+    markVirtualMethodAsReachable(invokedMethod, false, context, reason);
+    invokeAnalyses.forEach(analysis -> analysis.traceInvokeVirtual(invokedMethod, context));
   }
 
   void traceNewInstance(DexType type, ProgramMethod context) {
@@ -1592,13 +1557,11 @@
       return;
     }
 
-    DexClass clazz =
-        traceNewInstance(
-            type,
-            context,
-            InstantiationReason.NEW_INSTANCE_INSTRUCTION,
-            KeepReason.instantiatedIn(context));
-    newInstanceAnalyses.forEach(analysis -> analysis.traceNewInstance(type, clazz, context));
+    traceNewInstance(
+        type,
+        context,
+        InstantiationReason.NEW_INSTANCE_INSTRUCTION,
+        KeepReason.instantiatedIn(context));
   }
 
   void traceNewInstanceFromLambda(DexType type, ProgramMethod context) {
@@ -1606,22 +1569,19 @@
         type, context, InstantiationReason.LAMBDA, KeepReason.invokedFromLambdaCreatedIn(context));
   }
 
-  private DexClass traceNewInstance(
+  private void traceNewInstance(
       DexType type,
       ProgramMethod context,
       InstantiationReason instantiationReason,
       KeepReason keepReason) {
-    DexClass clazz = resolveBaseType(type, context);
-    if (clazz != null && clazz.isProgramClass()) {
-      DexProgramClass programClass = clazz.asProgramClass();
+    DexProgramClass clazz = getProgramClassOrNull(type, context);
+    if (clazz != null) {
       if (clazz.isAnnotation() || clazz.isInterface()) {
-        markTypeAsLive(programClass, graphReporter.registerClass(programClass, keepReason));
+        markTypeAsLive(clazz, graphReporter.registerClass(clazz, keepReason));
       } else {
-        worklist.enqueueMarkInstantiatedAction(
-            programClass, context, instantiationReason, keepReason);
+        worklist.enqueueMarkInstantiatedAction(clazz, context, instantiationReason, keepReason);
       }
     }
-    return clazz;
   }
 
   void traceInstanceFieldRead(DexField field, ProgramMethod currentMethod) {
@@ -2387,12 +2347,13 @@
         appView, annotatedItem, annotation, isLive, annotatedKind, mode);
   }
 
-  private DexClass resolveBaseType(DexType type, ProgramDefinition context) {
+  private DexProgramClass resolveBaseType(DexType type, ProgramDefinition context) {
     if (type.isArrayType()) {
       return resolveBaseType(type.toBaseType(appView.dexItemFactory()), context);
     }
     if (type.isClassType()) {
-      DexClass clazz = appView.definitionFor(type, context.getContextClass());
+      DexProgramClass clazz =
+          asProgramClassOrNull(appView.definitionFor(type, context.getContextClass()));
       if (clazz != null) {
         checkAccess(clazz, context);
       }
@@ -2453,33 +2414,32 @@
     return methodResolutionResult;
   }
 
-  private MethodResolutionResult handleInvokeOfStaticTarget(
+  private void handleInvokeOfStaticTarget(
       DexMethod reference, ProgramDefinition context, KeepReason reason) {
-    MethodResolutionResult resolutionResults = resolveMethod(reference, context, reason);
-    resolutionResults.forEachMethodResolutionResult(
-        resolutionResult -> {
-          if (!resolutionResult.isSingleResolution()) {
-            return;
-          }
-          SingleResolutionResult<?> resolution = resolutionResult.asSingleResolution();
-          if (resolution.getResolvedHolder().isNotProgramClass()) {
-            return;
-          }
-          DexProgramClass clazz = resolution.getResolvedHolder().asProgramClass();
-          DexEncodedMethod encodedMethod = resolution.getResolvedMethod();
+    resolveMethod(reference, context, reason)
+        .forEachMethodResolutionResult(
+            resolutionResult -> {
+              if (!resolutionResult.isSingleResolution()) {
+                return;
+              }
+              SingleResolutionResult<?> resolution = resolutionResult.asSingleResolution();
+              if (resolution.getResolvedHolder().isNotProgramClass()) {
+                return;
+              }
+              DexProgramClass clazz = resolution.getResolvedHolder().asProgramClass();
+              DexEncodedMethod encodedMethod = resolution.getResolvedMethod();
 
-          // We have to mark the resolved method as targeted even if it cannot actually be
-          // invoked to make sure the invocation will keep failing in the appropriate way.
-          ProgramMethod method = new ProgramMethod(clazz, encodedMethod);
-          markMethodAsTargeted(method, reason);
+              // We have to mark the resolved method as targeted even if it cannot actually be
+              // invoked to make sure the invocation will keep failing in the appropriate way.
+              ProgramMethod method = new ProgramMethod(clazz, encodedMethod);
+              markMethodAsTargeted(method, reason);
 
-          // Only mark methods for which invocation will succeed at runtime live.
-          if (encodedMethod.isStatic()) {
-            markDirectAndIndirectClassInitializersAsLive(clazz);
-            markDirectStaticOrConstructorMethodAsLive(method, reason);
-          }
-        });
-    return resolutionResults;
+              // Only mark methods for which invocation will succeed at runtime live.
+              if (encodedMethod.isStatic()) {
+                markDirectAndIndirectClassInitializersAsLive(clazz);
+                markDirectStaticOrConstructorMethodAsLive(method, reason);
+              }
+            });
   }
 
   void markDirectAndIndirectClassInitializersAsLive(DexProgramClass clazz) {
@@ -2583,44 +2543,43 @@
     handleInvokeOfDirectTarget(method, context, reason);
   }
 
-  private MethodResolutionResult handleInvokeOfDirectTarget(
+  private void handleInvokeOfDirectTarget(
       DexMethod reference, ProgramDefinition context, KeepReason reason) {
-    MethodResolutionResult resolutionResults = resolveMethod(reference, context, reason);
-    resolutionResults.forEachMethodResolutionResult(
-        resolutionResult -> {
-          if (resolutionResult.isFailedResolution()) {
-            failedMethodResolutionTargets.add(reference);
-            return;
-          }
+    resolveMethod(reference, context, reason)
+        .forEachMethodResolutionResult(
+            resolutionResult -> {
+              if (resolutionResult.isFailedResolution()) {
+                failedMethodResolutionTargets.add(reference);
+                return;
+              }
 
-          if (!resolutionResult.isSingleResolution()
-              || !resolutionResult.getResolvedHolder().isProgramClass()) {
-            return;
-          }
+              if (!resolutionResult.isSingleResolution()
+                  || !resolutionResult.getResolvedHolder().isProgramClass()) {
+                return;
+              }
 
-          ProgramMethod resolvedMethod =
-              resolutionResult.asSingleResolution().getResolvedProgramMethod();
+              ProgramMethod resolvedMethod =
+                  resolutionResult.asSingleResolution().getResolvedProgramMethod();
 
-          // We have to mark the resolved method as targeted even if it cannot actually be
-          // invoked to make sure the invocation will keep failing in the appropriate way.
-          markMethodAsTargeted(resolvedMethod, reason);
+              // We have to mark the resolved method as targeted even if it cannot actually be
+              // invoked to make sure the invocation will keep failing in the appropriate way.
+              markMethodAsTargeted(resolvedMethod, reason);
 
-          // Only mark methods for which invocation will succeed at runtime live.
-          if (resolvedMethod.getAccessFlags().isStatic()) {
-            return;
-          }
+              // Only mark methods for which invocation will succeed at runtime live.
+              if (resolvedMethod.getAccessFlags().isStatic()) {
+                return;
+              }
 
-          markDirectStaticOrConstructorMethodAsLive(resolvedMethod, reason);
+              markDirectStaticOrConstructorMethodAsLive(resolvedMethod, reason);
 
-          // It is valid to have an invoke-direct instruction in a default interface method that
-          // targets another default method in the same interface. In a class, that would lead
-          // to a verification error. See also testInvokeSpecialToDefaultMethod.
-          if (resolvedMethod.getDefinition().isNonPrivateVirtualMethod()
-              && virtualMethodsTargetedByInvokeDirect.add(resolvedMethod.getReference())) {
-            worklist.enqueueMarkMethodLiveAction(resolvedMethod, context, reason);
-          }
-        });
-    return resolutionResults;
+              // It is valid to have an invoke-direct instruction in a default interface method that
+              // targets another default method in the same interface. In a class, that would lead
+              // to a verification error. See also testInvokeSpecialToDefaultMethod.
+              if (resolvedMethod.getDefinition().isNonPrivateVirtualMethod()
+                  && virtualMethodsTargetedByInvokeDirect.add(resolvedMethod.getReference())) {
+                worklist.enqueueMarkMethodLiveAction(resolvedMethod, context, reason);
+              }
+            });
   }
 
   private void ensureFromLibraryOrThrow(DexType type, DexLibraryClass context) {
@@ -3384,91 +3343,89 @@
     liveTypes.getItems().forEach(consumer);
   }
 
-  private MethodResolutionResult markVirtualMethodAsReachable(
+  private void markVirtualMethodAsReachable(
       DexMethod method, boolean interfaceInvoke, ProgramMethod context, KeepReason reason) {
-    MethodResolutionResult resolutionResults =
-        resolveMethod(method, context, reason, interfaceInvoke);
-    if (method.getHolderType().isArrayType()) {
+    if (method.holder.isArrayType()) {
       // This is an array type, so the actual class will be generated at runtime. We treat this
       // like an invoke on a direct subtype of java.lang.Object that has no further subtypes.
       // As it has no subtypes, it cannot affect liveness of the program we are processing.
       // Ergo, we can ignore it. We need to make sure that the element type is available, though.
-      markTypeAsLive(method.getHolderType(), context, reason);
-      return resolutionResults;
+      markTypeAsLive(method.holder, context, reason);
+      return;
     }
 
-    resolutionResults.forEachMethodResolutionResult(
-        resolutionResult -> {
-          if (!resolutionResult.isSingleResolution()) {
-            return;
-          }
-          SingleResolutionResult<?> resolution = resolutionResult.asSingleResolution();
-          // Note that all virtual methods derived from library methods are kept regardless of
-          // being reachable, so the following only needs to consider reachable targets in the
-          // program.
-          // TODO(b/70160030): Revise this to support tree shaking library methods on
-          //  non-escaping types.
-          DexProgramClass initialResolutionHolder =
-              resolution.getInitialResolutionHolder().asProgramClass();
-          if (initialResolutionHolder == null) {
-            recordMethodReference(method, context);
-            return;
-          }
+    resolveMethod(method, context, reason, interfaceInvoke)
+        .forEachMethodResolutionResult(
+            resolutionResult -> {
+              if (!resolutionResult.isSingleResolution()) {
+                return;
+              }
+              SingleResolutionResult<?> resolution = resolutionResult.asSingleResolution();
+              // Note that all virtual methods derived from library methods are kept regardless of
+              // being reachable, so the following only needs to consider reachable targets in the
+              // program.
+              // TODO(b/70160030): Revise this to support tree shaking library methods on
+              //  non-escaping types.
+              DexProgramClass initialResolutionHolder =
+                  resolution.getInitialResolutionHolder().asProgramClass();
+              if (initialResolutionHolder == null) {
+                recordMethodReference(method, context);
+                return;
+              }
 
-          if (resolution.getResolvedHolder().isNotProgramClass()) {
-            // TODO(b/70160030): If the resolution is on a library method, then the keep edge
-            //  needs to go directly to the target method in the program. Thus this method will
-            //  need to ensure that 'reason' is not already reported (eg, must be delayed /
-            //  non-witness) and report that for each possible target edge below.
-            return;
-          }
+              if (resolution.getResolvedHolder().isNotProgramClass()) {
+                // TODO(b/70160030): If the resolution is on a library method, then the keep edge
+                //  needs to go directly to the target method in the program. Thus this method will
+                //  need to ensure that 'reason' is not already reported (eg, must be delayed /
+                //  non-witness) and report that for each possible target edge below.
+                return;
+              }
 
-          DexProgramClass contextHolder = context.getContextClass();
-          // If the method has already been marked, just report the new reason for the resolved
-          // target and save the context to ensure correct lookup of virtual dispatch targets.
-          ResolutionSearchKey resolutionSearchKey =
-              new ResolutionSearchKey(method, interfaceInvoke);
-          ProgramMethodSet seenContexts =
-              getReachableVirtualTargets(initialResolutionHolder).get(resolutionSearchKey);
-          if (seenContexts != null) {
-            seenContexts.add(context);
-            graphReporter.registerMethod(resolution.getResolvedMethod(), reason);
-            return;
-          }
+              DexProgramClass contextHolder = context.getContextClass();
+              // If the method has already been marked, just report the new reason for the resolved
+              // target and save the context to ensure correct lookup of virtual dispatch targets.
+              ResolutionSearchKey resolutionSearchKey =
+                  new ResolutionSearchKey(method, interfaceInvoke);
+              ProgramMethodSet seenContexts =
+                  getReachableVirtualTargets(initialResolutionHolder).get(resolutionSearchKey);
+              if (seenContexts != null) {
+                seenContexts.add(context);
+                graphReporter.registerMethod(resolution.getResolvedMethod(), reason);
+                return;
+              }
 
-          // We have to mark the resolution targeted, even if it does not become live, we
-          // need at least an abstract version of it so that it can be targeted.
-          DexProgramClass resolvedHolder = resolution.getResolvedHolder().asProgramClass();
-          DexEncodedMethod resolvedMethod = resolution.getResolvedMethod();
-          markMethodAsTargeted(new ProgramMethod(resolvedHolder, resolvedMethod), reason);
-          if (resolution.isAccessibleForVirtualDispatchFrom(contextHolder, appView).isFalse()) {
-            // Not accessible from this context, so this call will cause a runtime exception.
-            return;
-          }
+              // We have to mark the resolution targeted, even if it does not become live, we
+              // need at least an abstract version of it so that it can be targeted.
+              DexProgramClass resolvedHolder = resolution.getResolvedHolder().asProgramClass();
+              DexEncodedMethod resolvedMethod = resolution.getResolvedMethod();
+              markMethodAsTargeted(new ProgramMethod(resolvedHolder, resolvedMethod), reason);
+              if (resolution.isAccessibleForVirtualDispatchFrom(contextHolder, appView).isFalse()) {
+                // Not accessible from this context, so this call will cause a runtime exception.
+                return;
+              }
 
-          // The method resolved and is accessible, so currently live overrides become live.
-          reachableVirtualTargets
-              .computeIfAbsent(initialResolutionHolder, ignoreArgument(HashMap::new))
-              .computeIfAbsent(resolutionSearchKey, ignoreArgument(ProgramMethodSet::create))
-              .add(context);
+              // The method resolved and is accessible, so currently live overrides become live.
+              reachableVirtualTargets
+                  .computeIfAbsent(initialResolutionHolder, ignoreArgument(HashMap::new))
+                  .computeIfAbsent(resolutionSearchKey, ignoreArgument(ProgramMethodSet::create))
+                  .add(context);
 
-          resolution
-              .lookupVirtualDispatchTargets(
-                  contextHolder,
-                  appView,
-                  (type, subTypeConsumer, lambdaConsumer) ->
-                      objectAllocationInfoCollection.forEachInstantiatedSubType(
-                          type, subTypeConsumer, lambdaConsumer, appInfo),
-                  definition -> keepInfo.isPinned(definition, options, appInfo))
-              .forEach(
-                  target ->
-                      markVirtualDispatchTargetAsLive(
-                          target,
-                          programMethod ->
-                              graphReporter.reportReachableMethodAsLive(
-                                  resolvedMethod.getReference(), programMethod)));
-        });
-    return resolutionResults;
+              resolution
+                  .lookupVirtualDispatchTargets(
+                      contextHolder,
+                      appView,
+                      (type, subTypeConsumer, lambdaConsumer) ->
+                          objectAllocationInfoCollection.forEachInstantiatedSubType(
+                              type, subTypeConsumer, lambdaConsumer, appInfo),
+                      definition -> keepInfo.isPinned(definition, options, appInfo))
+                  .forEach(
+                      target ->
+                          markVirtualDispatchTargetAsLive(
+                              target,
+                              programMethod ->
+                                  graphReporter.reportReachableMethodAsLive(
+                                      resolvedMethod.getReference(), programMethod)));
+            });
   }
 
   private void markVirtualDispatchTargetAsLive(
@@ -3585,56 +3542,54 @@
   }
 
   // Package protected due to entry point from worklist.
-  void markSuperMethodAsReachable(DexMethod reference, ProgramMethod context) {
-    KeepReason reason = KeepReason.targetedBySuperFrom(context);
-    MethodResolutionResult resolutionResults = resolveMethod(reference, context, reason);
-    resolutionResults.forEachMethodResolutionResult(
-        resolutionResult -> {
-          if (!resolutionResult.isSingleResolution()) {
-            return;
-          }
-          SingleResolutionResult<?> resolution = resolutionResult.asSingleResolution();
-          // If the resolution is in the program, mark it targeted.
-          if (resolution.getResolvedHolder().isProgramClass()) {
-            markMethodAsTargeted(
-                new ProgramMethod(
-                    resolution.getResolvedHolder().asProgramClass(),
-                    resolution.getResolvedMethod()),
-                reason);
-          }
-          // If invoke target is invalid (inaccessible or not an instance-method) record it and
-          // stop.
-          DexClassAndMethod target =
-              resolution.lookupInvokeSuperTarget(context.getHolder(), appView);
-          if (target == null) {
-            failedMethodResolutionTargets.add(resolution.getResolvedMethod().getReference());
-            analyses.forEach(
-                analyses ->
-                    analyses.notifyFailedMethodResolutionTarget(
-                        resolution.getResolvedMethod(), worklist));
-            return;
-          }
-
-          DexProgramClass clazz = target.getHolder().asProgramClass();
-          if (clazz == null) {
-            return;
-          }
-
-          ProgramMethod method = target.asProgramMethod();
-
-          if (superInvokeDependencies
-              .computeIfAbsent(context.getDefinition(), ignore -> ProgramMethodSet.create())
-              .add(method)) {
-            if (liveMethods.contains(context)) {
-              markMethodAsTargeted(method, KeepReason.invokedViaSuperFrom(context));
-              if (!target.getAccessFlags().isAbstract()) {
-                markVirtualMethodAsLive(method, KeepReason.invokedViaSuperFrom(context));
+  void markSuperMethodAsReachable(DexMethod reference, ProgramMethod from) {
+    KeepReason reason = KeepReason.targetedBySuperFrom(from);
+    resolveMethod(reference, from, reason)
+        .forEachMethodResolutionResult(
+            resolutionResult -> {
+              if (!resolutionResult.isSingleResolution()) {
+                return;
               }
-            }
-          }
-        });
-    invokeAnalyses.forEach(
-        analysis -> analysis.traceInvokeSuper(reference, resolutionResults, context));
+              SingleResolutionResult<?> resolution = resolutionResult.asSingleResolution();
+              // If the resolution is in the program, mark it targeted.
+              if (resolution.getResolvedHolder().isProgramClass()) {
+                markMethodAsTargeted(
+                    new ProgramMethod(
+                        resolution.getResolvedHolder().asProgramClass(),
+                        resolution.getResolvedMethod()),
+                    reason);
+              }
+              // If invoke target is invalid (inaccessible or not an instance-method) record it and
+              // stop.
+              DexClassAndMethod target =
+                  resolution.lookupInvokeSuperTarget(from.getHolder(), appView);
+              if (target == null) {
+                failedMethodResolutionTargets.add(resolution.getResolvedMethod().getReference());
+                analyses.forEach(
+                    analyses ->
+                        analyses.notifyFailedMethodResolutionTarget(
+                            resolution.getResolvedMethod(), worklist));
+                return;
+              }
+
+              DexProgramClass clazz = target.getHolder().asProgramClass();
+              if (clazz == null) {
+                return;
+              }
+
+              ProgramMethod method = target.asProgramMethod();
+
+              if (superInvokeDependencies
+                  .computeIfAbsent(from.getDefinition(), ignore -> ProgramMethodSet.create())
+                  .add(method)) {
+                if (liveMethods.contains(from)) {
+                  markMethodAsTargeted(method, KeepReason.invokedViaSuperFrom(from));
+                  if (!target.getAccessFlags().isAbstract()) {
+                    markVirtualMethodAsLive(method, KeepReason.invokedViaSuperFrom(from));
+                  }
+                }
+              }
+            });
   }
 
   // Returns the set of live types.
diff --git a/src/main/java/com/android/tools/r8/shaking/RuntimeTypeCheckInfo.java b/src/main/java/com/android/tools/r8/shaking/RuntimeTypeCheckInfo.java
index 045227d..5b6511d 100644
--- a/src/main/java/com/android/tools/r8/shaking/RuntimeTypeCheckInfo.java
+++ b/src/main/java/com/android/tools/r8/shaking/RuntimeTypeCheckInfo.java
@@ -5,7 +5,6 @@
 package com.android.tools.r8.shaking;
 
 import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
@@ -84,22 +83,22 @@
     }
 
     @Override
-    public void traceCheckCast(DexType type, DexClass clazz, ProgramMethod context) {
+    public void traceCheckCast(DexType type, ProgramMethod context) {
       add(type, checkCastTypes);
     }
 
     @Override
-    public void traceSafeCheckCast(DexType type, DexClass clazz, ProgramMethod context) {
+    public void traceSafeCheckCast(DexType type, ProgramMethod context) {
       // Intentionally empty.
     }
 
     @Override
-    public void traceInstanceOf(DexType type, DexClass clazz, ProgramMethod context) {
+    public void traceInstanceOf(DexType type, ProgramMethod context) {
       add(type, instanceOfTypes);
     }
 
     @Override
-    public void traceExceptionGuard(DexType guard, DexClass clazz, ProgramMethod context) {
+    public void traceExceptionGuard(DexType guard, ProgramMethod context) {
       add(guard, exceptionGuardTypes);
     }
 
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 40b2d19..b71ad68 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -223,14 +223,6 @@
     return false;
   }
 
-  public boolean hasFeatureSplitConfiguration() {
-    return featureSplitConfiguration != null;
-  }
-
-  public FeatureSplitConfiguration getFeatureSplitConfiguration() {
-    return featureSplitConfiguration;
-  }
-
   public boolean hasProguardConfiguration() {
     return proguardConfiguration != null;
   }