// Copyright (c) 2019, 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.shaking;

import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
import static com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult.isOverriding;
import static com.android.tools.r8.utils.collections.ThrowingSet.isThrowingSet;

import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.features.ClassToFeatureSplitMap;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.Definition;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndField;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexClasspathClass;
import com.android.tools.r8.graph.DexDefinition;
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMember;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DirectMappedDexApplication;
import com.android.tools.r8.graph.DispatchTargetLookupResult;
import com.android.tools.r8.graph.FieldAccessInfo;
import com.android.tools.r8.graph.FieldAccessInfoCollection;
import com.android.tools.r8.graph.FieldAccessInfoCollectionImpl;
import com.android.tools.r8.graph.FieldResolutionResult;
import com.android.tools.r8.graph.InstantiatedSubTypeInfo;
import com.android.tools.r8.graph.LookupMethodTarget;
import com.android.tools.r8.graph.LookupResult.LookupResultSuccess;
import com.android.tools.r8.graph.LookupTarget;
import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
import com.android.tools.r8.graph.ObjectAllocationInfoCollection;
import com.android.tools.r8.graph.ObjectAllocationInfoCollectionImpl;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.graph.SingleDispatchTargetLookupResult;
import com.android.tools.r8.graph.UnknownDispatchTargetLookupResult;
import com.android.tools.r8.graph.lens.GraphLens;
import com.android.tools.r8.graph.lens.NonIdentityGraphLens;
import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.DynamicType;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.InvokeType;
import com.android.tools.r8.ir.desugar.LambdaDescriptor;
import com.android.tools.r8.ir.desugar.desugaredlibrary.apiconversion.DesugaredLibraryAPIConverter;
import com.android.tools.r8.naming.SeedMapper;
import com.android.tools.r8.repackaging.RepackagingUtils;
import com.android.tools.r8.shaking.KeepInfo.Joiner;
import com.android.tools.r8.synthesis.CommittedItems;
import com.android.tools.r8.threading.TaskCollection;
import com.android.tools.r8.utils.CollectionUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.PredicateSet;
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.Visibility;
import com.android.tools.r8.utils.collections.DexClassAndMethodSet;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import com.android.tools.r8.utils.collections.ThrowingSet;
import com.android.tools.r8.utils.structural.Ordered;
import com.google.common.collect.Sets;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import it.unimi.dsi.fastutil.objects.Object2BooleanMap;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/** Encapsulates liveness and reachability information for an application. */
public class AppInfoWithLiveness extends AppInfoWithClassHierarchy
    implements InstantiatedSubTypeInfo {
  /** Set of reachable proto types that will be dead code eliminated. */
  private final Set<DexType> deadProtoTypes;
  /**
   * Set of types that are mentioned in the program. We at least need an empty abstract classitem
   * for these.
   */
  private final Set<DexType> liveTypes;
  /**
   * Set of methods that are the immediate target of an invoke. They might not actually be live but
   * are required so that invokes can find the method. If such a method is not live (i.e. not
   * contained in {@link #liveMethods}, it may be marked as abstract and its implementation may be
   * removed.
   */
  private Set<DexMethod> targetedMethods;

  /** Classes that lead to resolution errors such as non-existing or invalid targets. */
  private final Set<DexType> failedClassResolutionTargets;

  /** Method targets that lead to resolution errors such as non-existing or invalid targets. */
  private final Set<DexMethod> failedMethodResolutionTargets;

  /** Field targets that lead to resolution errors, such as non-existing or invalid targets. */
  private final Set<DexField> failedFieldResolutionTargets;

  /**
   * Set of program methods that are used as the bootstrap method for an invoke-dynamic instruction.
   */
  private final Set<DexMethod> bootstrapMethods;

  /** Set of virtual methods that are the immediate target of an invoke-direct. */
  private final Set<DexMethod> virtualMethodsTargetedByInvokeDirect;
  /**
   * Set of methods that belong to live classes and can be reached by invokes. These need to be
   * kept.
   */
  private Set<DexMethod> liveMethods;

  /**
   * Information about all fields that are accessed by the program. The information includes whether
   * a given field is read/written by the program, and it also includes all indirect accesses to
   * each field. The latter is used, for example, during member rebinding.
   */
  private final FieldAccessInfoCollectionImpl fieldAccessInfoCollection;

  /** Information about instantiated classes and their allocation sites. */
  private final ObjectAllocationInfoCollectionImpl objectAllocationInfoCollection;
  /**
   * Set of live call sites in the code. Note that if desugaring has taken place call site objects
   * will have been removed from the code.
   */
  public final Map<DexCallSite, ProgramMethodSet> callSites;
  /** Collection of keep requirements for the program. */
  private final KeepInfoCollection keepInfo;
  /** All items with assumemayhavesideeffects rule. */
  public final Map<DexReference, ProguardMemberRule> mayHaveSideEffects;
  /** All methods that should be inlined if possible due to a configuration directive. */
  private final Set<DexMethod> alwaysInline;
  /** Items for which to print inlining decisions for (testing only). */
  private final Set<DexMethod> whyAreYouNotInlining;
  /** All methods that must be reprocessed (testing only). */
  private final Set<DexMethod> reprocess;
  /** All types that should be inlined if possible due to a configuration directive. */
  public final PredicateSet<DexType> alwaysClassInline;
  /**
   * Set of lock candidates (i.e., types whose class reference may flow to a monitor instruction).
   */
  private final Set<DexType> lockCandidates;
  /**
   * A map from seen init-class references to the minimum required visibility of the corresponding
   * static field.
   */
  public final Map<DexType, Visibility> initClassReferences;
  /**
   * Set of all methods including a RecordFieldValues instruction. Set only in final tree shaking.
   */
  public final Set<DexMethod> recordFieldValuesReferences;
  /**
   * All items with -identifiernamestring rule. Bound boolean value indicates the rule is explicitly
   * specified by users (<code>true</code>) or not, i.e., implicitly added by R8 (<code>false</code>
   * ).
   */
  public final Object2BooleanMap<DexMember<?, ?>> identifierNameStrings;
  /** A set of types that have been removed by the {@link TreePruner}. */
  final Set<DexType> prunedTypes;
  /** A map from switchmap class types to their corresponding switchmaps. */
  final Map<DexField, Int2ReferenceMap<DexField>> switchMaps;

  /* A cache to improve the lookup performance of lookupSingleVirtualTarget */
  private final SingleTargetLookupCache singleTargetLookupCache = new SingleTargetLookupCache();

  // TODO(zerny): Clean up the constructors so we have just one.
  AppInfoWithLiveness(
      CommittedItems committedItems,
      ClassToFeatureSplitMap classToFeatureSplitMap,
      MainDexInfo mainDexInfo,
      MissingClasses missingClasses,
      Set<DexType> deadProtoTypes,
      Set<DexType> liveTypes,
      Set<DexMethod> targetedMethods,
      Set<DexType> failedClassResolutionTargets,
      Set<DexMethod> failedMethodResolutionTargets,
      Set<DexField> failedFieldResolutionTargets,
      Set<DexMethod> bootstrapMethods,
      Set<DexMethod> virtualMethodsTargetedByInvokeDirect,
      Set<DexMethod> liveMethods,
      FieldAccessInfoCollectionImpl fieldAccessInfoCollection,
      ObjectAllocationInfoCollectionImpl objectAllocationInfoCollection,
      Map<DexCallSite, ProgramMethodSet> callSites,
      KeepInfoCollection keepInfo,
      Map<DexReference, ProguardMemberRule> mayHaveSideEffects,
      Set<DexMethod> alwaysInline,
      Set<DexMethod> whyAreYouNotInlining,
      Set<DexMethod> reprocess,
      PredicateSet<DexType> alwaysClassInline,
      Object2BooleanMap<DexMember<?, ?>> identifierNameStrings,
      Set<DexType> prunedTypes,
      Map<DexField, Int2ReferenceMap<DexField>> switchMaps,
      Set<DexType> lockCandidates,
      Map<DexType, Visibility> initClassReferences,
      Set<DexMethod> recordFieldValuesReferences) {
    super(committedItems, classToFeatureSplitMap, mainDexInfo, missingClasses);
    this.deadProtoTypes = deadProtoTypes;
    this.liveTypes = liveTypes;
    this.targetedMethods = targetedMethods;
    this.failedClassResolutionTargets = failedClassResolutionTargets;
    this.failedMethodResolutionTargets = failedMethodResolutionTargets;
    this.failedFieldResolutionTargets = failedFieldResolutionTargets;
    this.bootstrapMethods = bootstrapMethods;
    this.virtualMethodsTargetedByInvokeDirect = virtualMethodsTargetedByInvokeDirect;
    this.liveMethods = liveMethods;
    this.fieldAccessInfoCollection = fieldAccessInfoCollection;
    this.objectAllocationInfoCollection = objectAllocationInfoCollection;
    this.keepInfo = keepInfo;
    this.mayHaveSideEffects = mayHaveSideEffects;
    this.callSites = callSites;
    this.alwaysInline = alwaysInline;
    this.whyAreYouNotInlining = whyAreYouNotInlining;
    this.reprocess = reprocess;
    this.alwaysClassInline = alwaysClassInline;
    this.identifierNameStrings = identifierNameStrings;
    this.prunedTypes = prunedTypes;
    this.switchMaps = switchMaps;
    this.lockCandidates = lockCandidates;
    this.initClassReferences = initClassReferences;
    this.recordFieldValuesReferences = recordFieldValuesReferences;
    assert verify();
  }

  private AppInfoWithLiveness(AppInfoWithLiveness previous, CommittedItems committedItems) {
    this(
        committedItems,
        previous.getClassToFeatureSplitMap(),
        previous.getMainDexInfo(),
        previous.getMissingClasses(),
        previous.deadProtoTypes,
        CollectionUtils.addAll(previous.liveTypes, committedItems.getCommittedProgramTypes()),
        previous.targetedMethods,
        previous.failedClassResolutionTargets,
        previous.failedMethodResolutionTargets,
        previous.failedFieldResolutionTargets,
        previous.bootstrapMethods,
        previous.virtualMethodsTargetedByInvokeDirect,
        previous.liveMethods,
        previous.fieldAccessInfoCollection,
        previous.objectAllocationInfoCollection,
        previous.callSites,
        previous.keepInfo,
        previous.mayHaveSideEffects,
        previous.alwaysInline,
        previous.whyAreYouNotInlining,
        previous.reprocess,
        previous.alwaysClassInline,
        previous.identifierNameStrings,
        previous.prunedTypes,
        previous.switchMaps,
        previous.lockCandidates,
        previous.initClassReferences,
        previous.recordFieldValuesReferences);
  }

  private AppInfoWithLiveness(
      AppInfoWithLiveness previous, PrunedItems prunedItems, TaskCollection<?> tasks)
      throws ExecutionException {
    this(
        previous.getSyntheticItems().commitPrunedItems(prunedItems),
        previous.getClassToFeatureSplitMap().withoutPrunedItems(prunedItems),
        previous.getMainDexInfo().withoutPrunedItems(prunedItems),
        previous.getMissingClasses(),
        previous.deadProtoTypes,
        pruneClasses(previous.liveTypes, prunedItems, tasks),
        pruneMethods(previous.targetedMethods, prunedItems, tasks),
        pruneClasses(previous.failedClassResolutionTargets, prunedItems, tasks),
        pruneMethods(previous.failedMethodResolutionTargets, prunedItems, tasks),
        pruneFields(previous.failedFieldResolutionTargets, prunedItems, tasks),
        pruneMethods(previous.bootstrapMethods, prunedItems, tasks),
        pruneMethods(previous.virtualMethodsTargetedByInvokeDirect, prunedItems, tasks),
        pruneMethods(previous.liveMethods, prunedItems, tasks),
        previous.fieldAccessInfoCollection.withoutPrunedItems(prunedItems),
        previous.objectAllocationInfoCollection.withoutPrunedItems(prunedItems),
        pruneCallSites(previous.callSites, prunedItems),
        extendPinnedItems(previous, prunedItems.getAdditionalPinnedItems()),
        previous.mayHaveSideEffects,
        pruneMethods(previous.alwaysInline, prunedItems, tasks),
        pruneMethods(previous.whyAreYouNotInlining, prunedItems, tasks),
        pruneMethods(previous.reprocess, prunedItems, tasks),
        previous.alwaysClassInline,
        pruneMapFromMembers(previous.identifierNameStrings, prunedItems, tasks),
        prunedItems.hasRemovedClasses()
            ? CollectionUtils.mergeSets(previous.prunedTypes, prunedItems.getRemovedClasses())
            : previous.prunedTypes,
        previous.switchMaps,
        pruneClasses(previous.lockCandidates, prunedItems, tasks),
        pruneMapFromClasses(previous.initClassReferences, prunedItems, tasks),
        previous.recordFieldValuesReferences);
  }

  private static Map<DexCallSite, ProgramMethodSet> pruneCallSites(
      Map<DexCallSite, ProgramMethodSet> callSites, PrunedItems prunedItems) {
    callSites
        .entrySet()
        .removeIf(
            entry -> {
              ProgramMethodSet contexts = entry.getValue();
              ProgramMethodSet prunedContexts = contexts.withoutPrunedItems(prunedItems);
              if (prunedContexts.isEmpty()) {
                return true;
              }
              entry.setValue(prunedContexts);
              return false;
            });
    return callSites;
  }

  private static Set<DexType> pruneClasses(
      Set<DexType> methods, PrunedItems prunedItems, TaskCollection<?> tasks)
      throws ExecutionException {
    return pruneItems(methods, prunedItems.getRemovedClasses(), tasks);
  }

  private static Set<DexField> pruneFields(
      Set<DexField> fields, PrunedItems prunedItems, TaskCollection<?> tasks)
      throws ExecutionException {
    return pruneItems(fields, prunedItems.getRemovedFields(), tasks);
  }

  private static Set<DexMethod> pruneMethods(
      Set<DexMethod> methods, PrunedItems prunedItems, TaskCollection<?> tasks)
      throws ExecutionException {
    return pruneItems(methods, prunedItems.getRemovedMethods(), tasks);
  }

  private static <T> Set<T> pruneItems(Set<T> items, Set<T> removedItems, TaskCollection<?> tasks)
      throws ExecutionException {
    if (!isThrowingSet(items) && !removedItems.isEmpty()) {
      tasks.submit(
          () -> {
            if (items.size() <= removedItems.size()) {
              items.removeAll(removedItems);
            } else {
              removedItems.forEach(items::remove);
            }
          });
    }
    return items;
  }

  private static <V> Map<DexType, V> pruneMapFromClasses(
      Map<DexType, V> map, PrunedItems prunedItems, TaskCollection<?> tasks)
      throws ExecutionException {
    return pruneMap(map, prunedItems.getRemovedClasses(), tasks);
  }

  private static Object2BooleanMap<DexMember<?, ?>> pruneMapFromMembers(
      Object2BooleanMap<DexMember<?, ?>> map, PrunedItems prunedItems, TaskCollection<?> tasks)
      throws ExecutionException {
    if (prunedItems.hasRemovedMembers()) {
      tasks.submit(
          () -> {
            prunedItems.getRemovedFields().forEach(map::removeBoolean);
            prunedItems.getRemovedMethods().forEach(map::removeBoolean);
          });
    }
    return map;
  }

  private static <K, V> Map<K, V> pruneMap(
      Map<K, V> map, Set<K> removedItems, TaskCollection<?> tasks) throws ExecutionException {
    if (!removedItems.isEmpty()) {
      tasks.submit(
          () -> {
            if (map.size() <= removedItems.size()) {
              map.keySet().removeAll(removedItems);
            } else {
              removedItems.forEach(map::remove);
            }
          });
    }
    return map;
  }

  public void notifyMemberRebindingFinished(AppView<AppInfoWithLiveness> appView) {
    getFieldAccessInfoCollection().restrictToProgram(appView);
  }

  @Override
  public void notifyMinifierFinished() {
    liveMethods = ThrowingSet.get();
  }

  public void notifyTreePrunerFinished(Enqueuer.Mode mode) {
    if (mode.isInitialTreeShaking()) {
      liveMethods = ThrowingSet.get();
    }
    targetedMethods = ThrowingSet.get();
  }

  private boolean verify() {
    assert keepInfo.verifyPinnedTypesAreLive(liveTypes, options());
    assert objectAllocationInfoCollection.verifyAllocatedTypesAreLive(
        liveTypes, getMissingClasses(), this);
    return true;
  }

  @Override
  public AppInfoWithLiveness rebuildWithMainDexInfo(MainDexInfo mainDexInfo) {
    return new AppInfoWithLiveness(
        getSyntheticItems().commit(app()),
        getClassToFeatureSplitMap(),
        mainDexInfo,
        getMissingClasses(),
        deadProtoTypes,
        liveTypes,
        targetedMethods,
        failedClassResolutionTargets,
        failedMethodResolutionTargets,
        failedFieldResolutionTargets,
        bootstrapMethods,
        virtualMethodsTargetedByInvokeDirect,
        liveMethods,
        fieldAccessInfoCollection,
        objectAllocationInfoCollection,
        callSites,
        keepInfo,
        mayHaveSideEffects,
        alwaysInline,
        whyAreYouNotInlining,
        reprocess,
        alwaysClassInline,
        identifierNameStrings,
        prunedTypes,
        switchMaps,
        lockCandidates,
        initClassReferences,
        recordFieldValuesReferences);
  }

  private static KeepInfoCollection extendPinnedItems(
      AppInfoWithLiveness previous, Collection<? extends DexReference> additionalPinnedItems) {
    if (additionalPinnedItems == null || additionalPinnedItems.isEmpty()) {
      return previous.keepInfo;
    }
    return previous.keepInfo.mutate(
        collection -> {
          for (DexReference reference : additionalPinnedItems) {
            if (reference.isDexType()) {
              DexProgramClass clazz =
                  asProgramClassOrNull(previous.definitionFor(reference.asDexType()));
              if (clazz != null) {
                collection.joinClass(clazz, Joiner::disallowShrinking);
              }
            } else if (reference.isDexMethod()) {
              DexMethod method = reference.asDexMethod();
              DexProgramClass clazz = asProgramClassOrNull(previous.definitionFor(method.holder));
              if (clazz != null) {
                ProgramMethod definition = clazz.lookupProgramMethod(method);
                if (definition != null) {
                  collection.joinMethod(definition, Joiner::disallowShrinking);
                }
              }
            } else {
              DexField field = reference.asDexField();
              DexProgramClass clazz = asProgramClassOrNull(previous.definitionFor(field.holder));
              if (clazz != null) {
                ProgramField definition = clazz.lookupProgramField(field);
                if (definition != null) {
                  collection.joinField(definition, Joiner::disallowShrinking);
                }
              }
            }
          }
        });
  }

  public AppInfoWithLiveness(
      AppInfoWithLiveness previous, Map<DexField, Int2ReferenceMap<DexField>> switchMaps) {
    super(
        previous.getSyntheticItems().commit(previous.app()),
        previous.getClassToFeatureSplitMap(),
        previous.getMainDexInfo(),
        previous.getMissingClasses());
    this.deadProtoTypes = previous.deadProtoTypes;
    this.liveTypes = previous.liveTypes;
    this.targetedMethods = previous.targetedMethods;
    this.failedClassResolutionTargets = previous.failedClassResolutionTargets;
    this.failedMethodResolutionTargets = previous.failedMethodResolutionTargets;
    this.failedFieldResolutionTargets = previous.failedFieldResolutionTargets;
    this.bootstrapMethods = previous.bootstrapMethods;
    this.virtualMethodsTargetedByInvokeDirect = previous.virtualMethodsTargetedByInvokeDirect;
    this.liveMethods = previous.liveMethods;
    this.fieldAccessInfoCollection = previous.fieldAccessInfoCollection;
    this.objectAllocationInfoCollection = previous.objectAllocationInfoCollection;
    this.keepInfo = previous.keepInfo;
    this.mayHaveSideEffects = previous.mayHaveSideEffects;
    this.callSites = previous.callSites;
    this.alwaysInline = previous.alwaysInline;
    this.whyAreYouNotInlining = previous.whyAreYouNotInlining;
    this.reprocess = previous.reprocess;
    this.alwaysClassInline = previous.alwaysClassInline;
    this.identifierNameStrings = previous.identifierNameStrings;
    this.prunedTypes = previous.prunedTypes;
    this.switchMaps = switchMaps;
    this.lockCandidates = previous.lockCandidates;
    this.initClassReferences = previous.initClassReferences;
    this.recordFieldValuesReferences = previous.recordFieldValuesReferences;
    previous.markObsolete();
    assert verify();
  }

  public static AppInfoWithLivenessModifier modifier() {
    return new AppInfoWithLivenessModifier();
  }

  @Override
  public DexClass definitionFor(DexType type) {
    DexClass definition = super.definitionFor(type);
    assert definition != null
            || deadProtoTypes.contains(type)
            || getMissingClasses().contains(type)
            // TODO(b/150736225): Not sure how to remove these.
            || DesugaredLibraryAPIConverter.isVivifiedType(type)
        : "Failed lookup of non-missing type: " + type;
    return definition;
  }

  private CfVersion largestInputCfVersion = null;

  public boolean canUseConstClassInstructions(InternalOptions options) {
    if (!options.isGeneratingClassFiles()) {
      return true;
    }
    if (largestInputCfVersion == null) {
      computeLargestCfVersion();
    }
    return options.canUseConstClassInstructions(largestInputCfVersion);
  }

  private synchronized void computeLargestCfVersion() {
    if (largestInputCfVersion != null) {
      return;
    }
    for (DexProgramClass clazz : classes()) {
      // Skip synthetic classes which may not have a specified version.
      if (clazz.hasClassFileVersion()) {
        largestInputCfVersion =
            Ordered.maxIgnoreNull(largestInputCfVersion, clazz.getInitialClassFileVersion());
      }
    }
    assert largestInputCfVersion != null;
  }

  public boolean isLiveProgramClass(DexProgramClass clazz) {
    return liveTypes.contains(clazz.type);
  }

  public boolean isLiveProgramType(DexType type) {
    DexClass clazz = definitionFor(type);
    return clazz != null && clazz.isProgramClass() && isLiveProgramClass(clazz.asProgramClass());
  }

  public boolean isNonProgramTypeOrLiveProgramType(DexType type) {
    if (liveTypes.contains(type)) {
      return true;
    }
    if (prunedTypes.contains(type)) {
      return false;
    }
    DexClass clazz = definitionFor(type);
    return clazz == null || !clazz.isProgramClass();
  }

  public boolean isLiveMethod(DexMethod method) {
    return liveMethods.contains(method);
  }

  public boolean isTargetedMethod(DexMethod method) {
    return targetedMethods.contains(method);
  }

  public boolean isFailedClassResolutionTarget(DexType type) {
    return failedClassResolutionTargets.contains(type);
  }

  public boolean isFailedMethodResolutionTarget(DexMethod method) {
    return failedMethodResolutionTargets.contains(method);
  }

  public Set<DexMethod> getFailedMethodResolutionTargets() {
    return failedMethodResolutionTargets;
  }

  public boolean isFailedFieldResolutionTarget(DexField field) {
    return failedFieldResolutionTargets.contains(field);
  }

  public Set<DexField> getFailedFieldResolutionTargets() {
    return failedFieldResolutionTargets;
  }

  public boolean isBootstrapMethod(DexMethod method) {
    return bootstrapMethods.contains(method);
  }

  public boolean isBootstrapMethod(ProgramMethod method) {
    return isBootstrapMethod(method.getReference());
  }

  public Set<DexMethod> getVirtualMethodsTargetedByInvokeDirect() {
    return virtualMethodsTargetedByInvokeDirect;
  }

  public boolean isAlwaysInlineMethod(DexMethod method) {
    return alwaysInline.contains(method);
  }

  public boolean isWhyAreYouNotInliningMethod(DexMethod method) {
    return whyAreYouNotInlining.contains(method);
  }

  public boolean hasNoWhyAreYouNotInliningMethods() {
    return whyAreYouNotInlining.isEmpty();
  }

  public Set<DexMethod> getReprocessMethods() {
    return reprocess;
  }

  /**
   * Resolve the methods implemented by the lambda expression that created the {@code callSite}.
   *
   * <p>If {@code callSite} was not created as a result of a lambda expression (i.e. the metafactory
   * is not {@code LambdaMetafactory}), the empty set is returned.
   *
   * <p>If the metafactory is neither {@code LambdaMetafactory} nor {@code StringConcatFactory}, a
   * warning is issued.
   *
   * <p>The returned set of methods all have {@code callSite.methodName} as the method name.
   *
   * @param callSite Call site to resolve.
   * @return Methods implemented by the lambda expression that created the {@code callSite}.
   */
  @SuppressWarnings("ReferenceEquality")
  public DexClassAndMethodSet lookupLambdaImplementedMethods(
      DexCallSite callSite, AppView<AppInfoWithLiveness> appView) {
    assert checkIfObsolete();
    List<DexType> callSiteInterfaces = LambdaDescriptor.getInterfaces(callSite, appView);
    if (callSiteInterfaces == null || callSiteInterfaces.isEmpty()) {
      return DexClassAndMethodSet.empty();
    }
    DexClassAndMethodSet result = DexClassAndMethodSet.create();
    Deque<DexType> worklist = new ArrayDeque<>(callSiteInterfaces);
    Set<DexType> visited = Sets.newIdentityHashSet();
    while (!worklist.isEmpty()) {
      DexType iface = worklist.removeFirst();
      if (!visited.add(iface)) {
        // Already visited previously. May happen due to "diamond shapes" in the interface
        // hierarchy.
        continue;
      }
      DexClass clazz = definitionFor(iface);
      if (clazz == null) {
        // Skip this interface. If the lambda only implements missing library interfaces and not any
        // program interfaces, then minification and tree shaking are not interested in this
        // DexCallSite anyway, so skipping this interface is harmless. On the other hand, if
        // minification is run on a program with a lambda interface that implements both a missing
        // library interface and a present program interface, then we might minify the method name
        // on the program interface even though it should be kept the same as the (missing) library
        // interface method. That is a shame, but minification is not suited for incomplete programs
        // anyway.
        continue;
      }
      assert clazz.isInterface();
      for (DexClassAndMethod method : clazz.virtualClassMethods()) {
        if (method.getName().isIdenticalTo(callSite.methodName)
            && method.getAccessFlags().isAbstract()) {
          result.add(method);
        }
      }
      Collections.addAll(worklist, clazz.interfaces.values);
    }
    return result;
  }

  /**
   * Const-classes is a conservative set of types that may be lock-candidates and cannot be merged.
   * When using synchronized blocks, we cannot ensure that const-class locks will not flow in. This
   * can potentially cause incorrect behavior when merging classes. A conservative choice is to not
   * merge any const-class classes. More info at b/142438687.
   */
  public boolean isLockCandidate(DexProgramClass clazz) {
    return lockCandidates.contains(clazz.getType());
  }

  public Set<DexType> getDeadProtoTypes() {
    return deadProtoTypes;
  }

  public Int2ReferenceMap<DexField> getSwitchMap(DexField field) {
    assert checkIfObsolete();
    return switchMaps.get(field);
  }

  /** This method provides immutable access to `fieldAccessInfoCollection`. */
  public FieldAccessInfoCollection<? extends FieldAccessInfo> getFieldAccessInfoCollection() {
    return fieldAccessInfoCollection;
  }

  FieldAccessInfoCollectionImpl getMutableFieldAccessInfoCollection() {
    return fieldAccessInfoCollection;
  }

  /** This method provides immutable access to `objectAllocationInfoCollection`. */
  public ObjectAllocationInfoCollection getObjectAllocationInfoCollection() {
    return objectAllocationInfoCollection;
  }

  void mutateObjectAllocationInfoCollection(
      Consumer<ObjectAllocationInfoCollectionImpl.Builder> mutator) {
    objectAllocationInfoCollection.mutate(mutator, this);
  }

  void removeFromSingleTargetLookupCache(DexClass clazz) {
    singleTargetLookupCache.removeInstantiatedType(clazz.type, this);
  }

  private boolean isInstantiatedDirectly(DexProgramClass clazz) {
    assert checkIfObsolete();
    DexType type = clazz.type;
    return (!clazz.isInterface() && objectAllocationInfoCollection.isInstantiatedDirectly(clazz))
        // TODO(b/145344105): Model annotations in the object allocation info.
        || (clazz.isAnnotation() && liveTypes.contains(type));
  }

  public boolean isInstantiatedIndirectly(DexProgramClass clazz) {
    assert checkIfObsolete();
    return objectAllocationInfoCollection.hasInstantiatedStrictSubtype(clazz);
  }

  public boolean isInstantiatedDirectlyOrIndirectly(DexProgramClass clazz) {
    assert checkIfObsolete();
    return isInstantiatedDirectly(clazz) || isInstantiatedIndirectly(clazz);
  }

  public boolean isReachableOrReferencedField(DexEncodedField field) {
    assert checkIfObsolete();
    DexField reference = field.getReference();
    FieldAccessInfo info = getFieldAccessInfoCollection().get(reference);
    if (info != null) {
      assert info.isRead() || info.isWritten();
      return true;
    }
    assert getKeepInfo().getFieldInfo(field, this).isShrinkingAllowed(options());
    return false;
  }

  public boolean isFieldRead(DexClassAndField field) {
    assert checkIfObsolete();
    FieldAccessInfo info = getFieldAccessInfoCollection().get(field.getReference());
    if (info != null && info.isRead()) {
      return true;
    }
    if (isPinned(field)) {
      return true;
    }
    // For non-program classes we don't know whether a field is read.
    return !field.isProgramField();
  }

  public boolean isFieldWritten(DexClassAndField field) {
    assert checkIfObsolete();
    return isFieldWrittenByFieldPutInstruction(field) || isPinned(field);
  }

  public boolean isFieldWrittenByFieldPutInstruction(DexClassAndField field) {
    assert checkIfObsolete();
    FieldAccessInfo info = getFieldAccessInfoCollection().get(field.getReference());
    if (info != null && info.isWritten()) {
      // The field is written directly by the program itself.
      return true;
    }
    // For non-program classes we don't know whether a field is rewritten.
    return !field.isProgramField();
  }

  public boolean isFieldOnlyWrittenInMethod(DexClassAndField field, DexEncodedMethod method) {
    assert checkIfObsolete();
    assert isFieldWritten(field) : "Expected field `" + field.toSourceString() + "` to be written";
    if (isPinned(field)) {
      return false;
    }
    return isFieldOnlyWrittenInMethodIgnoringPinning(field, method);
  }

  public boolean isFieldOnlyWrittenInMethodIgnoringPinning(
      DexClassAndField field, DexEncodedMethod method) {
    assert checkIfObsolete();
    assert isFieldWritten(field) : "Expected field `" + field.toSourceString() + "` to be written";
    FieldAccessInfo fieldAccessInfo = getFieldAccessInfoCollection().get(field.getReference());
    return fieldAccessInfo != null
        && fieldAccessInfo.isWritten()
        && !fieldAccessInfo.isWrittenOutside(method);
  }

  @SuppressWarnings("ReferenceEquality")
  public boolean isInstanceFieldWrittenOnlyInInstanceInitializers(DexClassAndField field) {
    assert checkIfObsolete();
    assert isFieldWritten(field) : "Expected field `" + field.toSourceString() + "` to be written";
    if (isPinned(field)) {
      return false;
    }
    FieldAccessInfo fieldAccessInfo = getFieldAccessInfoCollection().get(field.getReference());
    if (fieldAccessInfo == null || !fieldAccessInfo.isWritten()) {
      return false;
    }
    DexType holder = field.getHolderType();
    return fieldAccessInfo.isWrittenOnlyInMethodSatisfying(
        method ->
            method.getHolderType() == holder && method.getDefinition().isInstanceInitializer());
  }

  public boolean isStaticFieldWrittenOnlyInEnclosingStaticInitializer(DexClassAndField field) {
    assert checkIfObsolete();
    assert isFieldWritten(field) : "Expected field `" + field.toSourceString() + "` to be written";
    DexEncodedMethod staticInitializer =
        definitionFor(field.getHolderType()).asProgramClass().getClassInitializer();
    return staticInitializer != null && isFieldOnlyWrittenInMethod(field, staticInitializer);
  }

  public boolean isInstantiatedInterface(DexProgramClass clazz) {
    assert checkIfObsolete();
    return objectAllocationInfoCollection.isInterfaceWithUnknownSubtypeHierarchy(clazz);
  }

  @Override
  public boolean hasLiveness() {
    assert checkIfObsolete();
    return true;
  }

  @Override
  public AppInfoWithLiveness withLiveness() {
    assert checkIfObsolete();
    return this;
  }

  public boolean isRepackagingAllowed(DexProgramClass clazz, AppView<?> appView) {
    if (!keepInfo.getInfo(clazz).isRepackagingAllowed(options())) {
      return false;
    }
    if (RepackagingUtils.isPackageNameKept(clazz, appView.options())) {
      return false;
    }
    SeedMapper applyMappingSeedMapper = appView.getApplyMappingSeedMapper();
    return applyMappingSeedMapper == null || !applyMappingSeedMapper.hasMapping(clazz.type);
  }

  @Deprecated
  public boolean isPinnedWithDefinitionLookup(DexReference reference) {
    assert checkIfObsolete();
    return keepInfo.isPinnedWithDefinitionLookup(reference, options(), this);
  }

  @Deprecated
  public boolean isPinned(DexDefinition definition) {
    return keepInfo.isPinned(definition, options(), this);
  }

  @Deprecated
  public boolean isPinned(DexProgramClass clazz) {
    return keepInfo.isPinned(clazz, options());
  }

  @Deprecated
  public boolean isPinned(Definition definition) {
    assert definition != null;
    return definition.isProgramDefinition()
        && keepInfo.isPinned(definition.asProgramDefinition(), options());
  }

  public boolean hasPinnedInstanceInitializer(DexType type) {
    assert type.isClassType();
    DexProgramClass clazz = asProgramClassOrNull(definitionFor(type));
    if (clazz != null) {
      for (ProgramMethod method : clazz.directProgramMethods()) {
        if (method.getDefinition().isInstanceInitializer() && isPinned(method)) {
          return true;
        }
      }
    }
    return false;
  }

  public KeepInfoCollection getKeepInfo() {
    return keepInfo;
  }

  /**
   * Returns a copy of this AppInfoWithLiveness where the set of classes is pruned using the given
   * DexApplication object.
   */
  @Override
  public AppInfoWithLiveness prunedCopyFrom(
      PrunedItems prunedItems, ExecutorService executorService, Timing timing)
      throws ExecutionException {
    assert getClass() == AppInfoWithLiveness.class;
    assert checkIfObsolete();
    if (prunedItems.isEmpty()) {
      assert app() == prunedItems.getPrunedApp();
      return this;
    }
    timing.begin("Pruning AppInfoWithLiveness");
    if (prunedItems.hasRemovedClasses()) {
      // Rebuild the hierarchy.
      objectAllocationInfoCollection.mutate(
          mutator -> mutator.removeAllocationsForPrunedItems(prunedItems), this);
      keepInfo.mutate(keepInfo -> keepInfo.removeKeepInfoForPrunedItems(prunedItems));
    } else if (prunedItems.hasRemovedMembers()) {
      keepInfo.mutate(keepInfo -> keepInfo.removeKeepInfoForPrunedItems(prunedItems));
    }
    TaskCollection<?> tasks = new TaskCollection<>(options(), executorService);
    AppInfoWithLiveness appInfoWithLiveness = new AppInfoWithLiveness(this, prunedItems, tasks);
    tasks.await();
    timing.end();
    return appInfoWithLiveness;
  }

  public AppInfoWithLiveness rebuildWithLiveness(DexApplication application) {
    return rebuildWithLiveness(getSyntheticItems().commit(application));
  }

  public AppInfoWithLiveness rebuildWithLiveness(CommittedItems committedItems) {
    return new AppInfoWithLiveness(this, committedItems);
  }

  public AppInfoWithLiveness rewrittenWithLens(
      DirectMappedDexApplication application,
      NonIdentityGraphLens lens,
      GraphLens appliedLens,
      Timing timing) {
    assert checkIfObsolete();

    // Switchmap classes should never be affected by renaming.
    assert lens.assertFieldsNotModified(
        switchMaps.keySet().stream()
            .map(this::resolveField)
            .filter(FieldResolutionResult::isSingleFieldResolutionResult)
            .map(FieldResolutionResult::getResolvedField)
            .collect(Collectors.toList()));

    CommittedItems committedItems =
        getSyntheticItems().commitRewrittenWithLens(application, lens, timing);
    DexDefinitionSupplier definitionSupplier =
        committedItems.getApplication().getDefinitionsSupplier(committedItems);
    return new AppInfoWithLiveness(
        committedItems,
        getClassToFeatureSplitMap().rewrittenWithLens(lens, timing),
        getMainDexInfo().rewrittenWithLens(getSyntheticItems(), lens, timing),
        getMissingClasses(),
        deadProtoTypes,
        lens.rewriteReferences(liveTypes),
        lens.rewriteReferences(targetedMethods),
        lens.rewriteReferences(failedClassResolutionTargets),
        lens.rewriteReferences(failedMethodResolutionTargets),
        lens.rewriteFields(failedFieldResolutionTargets, timing),
        lens.rewriteReferences(bootstrapMethods),
        lens.rewriteReferences(virtualMethodsTargetedByInvokeDirect),
        lens.rewriteReferences(liveMethods),
        fieldAccessInfoCollection.rewrittenWithLens(definitionSupplier, lens, timing),
        objectAllocationInfoCollection.rewrittenWithLens(
            definitionSupplier, lens, appliedLens, timing),
        lens.rewriteCallSites(callSites, definitionSupplier, timing),
        keepInfo.rewrite(definitionSupplier, lens, application.options, timing),
        // Take any rule in case of collisions.
        lens.rewriteReferenceKeys(mayHaveSideEffects, (reference, rules) -> ListUtils.first(rules)),
        lens.rewriteReferences(alwaysInline),
        lens.rewriteReferences(whyAreYouNotInlining),
        lens.rewriteReferences(reprocess),
        alwaysClassInline.rewriteItems(lens::lookupType),
        lens.rewriteReferenceKeys(identifierNameStrings),
        // Don't rewrite pruned types - the removed types are identified by their original name.
        prunedTypes,
        lens.rewriteFieldKeys(switchMaps),
        lens.rewriteReferences(lockCandidates),
        rewriteInitClassReferences(lens),
        lens.rewriteReferences(recordFieldValuesReferences));
  }

  public Map<DexType, Visibility> rewriteInitClassReferences(GraphLens lens) {
    return lens.rewriteTypeKeys(
        initClassReferences,
        (minimumRequiredVisibilityForCurrentMethod,
            otherMinimumRequiredVisibilityForCurrentMethod) -> {
          assert !minimumRequiredVisibilityForCurrentMethod.isPrivate();
          assert !otherMinimumRequiredVisibilityForCurrentMethod.isPrivate();
          if (minimumRequiredVisibilityForCurrentMethod.isPublic()
              || otherMinimumRequiredVisibilityForCurrentMethod.isPublic()) {
            return Visibility.PUBLIC;
          }
          if (minimumRequiredVisibilityForCurrentMethod.isProtected()
              || otherMinimumRequiredVisibilityForCurrentMethod.isProtected()) {
            return Visibility.PROTECTED;
          }
          return Visibility.PACKAGE_PRIVATE;
        });
  }

  /**
   * Returns true if the given type was part of the original program but has been removed during
   * tree shaking.
   */
  public boolean wasPruned(DexType type) {
    assert checkIfObsolete();
    return prunedTypes.contains(type);
  }

  public Set<DexType> getPrunedTypes() {
    assert checkIfObsolete();
    return prunedTypes;
  }

  public DexClassAndMethod lookupSingleTarget(
      AppView<AppInfoWithLiveness> appView,
      InvokeType type,
      DexMethod target,
      SingleResolutionResult<?> resolutionResult,
      ProgramMethod context,
      LibraryModeledPredicate modeledPredicate) {
    assert checkIfObsolete();
    if (!target.getHolderType().isClassType()) {
      return null;
    }
    switch (type) {
      case INTERFACE:
      case VIRTUAL:
        return lookupSingleVirtualTarget(
            appView,
            target,
            resolutionResult,
            context,
            type.isInterface(),
            modeledPredicate,
            DynamicType.unknown());
      case DIRECT:
        return lookupDirectTarget(target, context, appView);
      case STATIC:
        return lookupStaticTarget(target, context, appView);
      case SUPER:
        return lookupSuperTarget(target, context, appView);
      default:
        return null;
    }
  }

  /** For mapping invoke virtual instruction to single target method. */
  public DexClassAndMethod lookupSingleVirtualTargetForTesting(
      AppView<AppInfoWithLiveness> appView,
      DexMethod method,
      ProgramMethod context,
      boolean isInterface,
      LibraryModeledPredicate modeledPredicate,
      DynamicType dynamicReceiverType) {
    assert checkIfObsolete();
    SingleResolutionResult<?> resolutionResult =
        appView.appInfo().resolveMethodLegacy(method, isInterface).asSingleResolution();
    if (resolutionResult != null) {
      return lookupSingleVirtualTarget(
          appView,
          method,
          resolutionResult,
          context,
          isInterface,
          modeledPredicate,
          dynamicReceiverType);
    }
    return null;
  }

  public DexClassAndMethod lookupSingleVirtualTarget(
      AppView<AppInfoWithLiveness> appView,
      DexMethod method,
      SingleResolutionResult<?> resolutionResult,
      ProgramMethod context,
      boolean isInterface,
      LibraryModeledPredicate modeledPredicate,
      DynamicType dynamicReceiverType) {
    assert checkIfObsolete();
    assert dynamicReceiverType != null;
    if (method.getHolderType().isArrayType()) {
      return null;
    }
    TypeElement staticReceiverType = method.getHolderType().toTypeElement(appView);
    if (!appView
        .getOpenClosedInterfacesCollection()
        .isDefinitelyInstanceOfStaticType(appView, () -> dynamicReceiverType, staticReceiverType)) {
      return null;
    }
    DexClass initialResolutionHolder = resolutionResult.getInitialResolutionHolder();
    if (initialResolutionHolder.isInterface() != isInterface) {
      return null;
    }
    DexType refinedReceiverType =
        TypeAnalysis.toRefinedReceiverType(dynamicReceiverType, method, appView);
    DexClass refinedReceiverClass = definitionFor(refinedReceiverType);
    if (refinedReceiverClass == null) {
      // The refined receiver is not defined in the program and we cannot determine the target.
      return null;
    }
    if (singleTargetLookupCache.hasPositiveCacheHit(refinedReceiverType, method)) {
      return singleTargetLookupCache.getPositiveCacheHit(refinedReceiverType, method);
    }
    if (!dynamicReceiverType.hasDynamicLowerBoundType()
        && singleTargetLookupCache.hasNegativeCacheHit(refinedReceiverType, method)) {
      return null;
    }
    if (resolutionResult
        .isAccessibleForVirtualDispatchFrom(context.getHolder(), appView)
        .isFalse()) {
      return null;
    }
    // If the resolved method is final, return the resolution.
    DexClassAndMethod resolvedMethod = resolutionResult.getResolutionPair();
    if (resolvedMethod.getHolder().isFinal() || resolvedMethod.getAccessFlags().isFinal()) {
      if (!resolvedMethod.isLibraryMethod()
          || modeledPredicate.isModeled(resolvedMethod.getHolderType())) {
        return singleTargetLookupCache.addToCache(refinedReceiverType, method, resolvedMethod);
      }
    }
    DispatchTargetLookupResult exactTarget =
        getMethodTargetFromExactRuntimeInformation(
            refinedReceiverType,
            dynamicReceiverType.getDynamicLowerBoundType(),
            resolutionResult,
            refinedReceiverClass);
    if (exactTarget != null) {
      // We are not caching single targets here because the cache does not include the
      // lower bound dimension.
      return exactTarget.isSingleResult()
          ? exactTarget.asSingleResult().getSingleDispatchTarget()
          : null;
    }
    if (refinedReceiverClass.isNotProgramClass()) {
      // The refined receiver is not defined in the program and we cannot determine the target.
      singleTargetLookupCache.addNoSingleTargetToCache(refinedReceiverType, method);
      return null;
    }
    DexClass resolvedHolder = resolutionResult.getResolvedHolder();
    // TODO(b/148769279): Disable lookup single target on lambda's for now.
    if (resolvedHolder.isInterface()
        && resolvedHolder.isProgramClass()
        && objectAllocationInfoCollection.isImmediateInterfaceOfInstantiatedLambda(
            resolvedHolder.asProgramClass())) {
      singleTargetLookupCache.addNoSingleTargetToCache(refinedReceiverType, method);
      return null;
    }
    DexClassAndMethod singleMethodTarget = null;
    DexProgramClass refinedLowerBound = null;
    if (dynamicReceiverType.hasDynamicLowerBoundType()) {
      DexClass refinedLowerBoundClass =
          definitionFor(dynamicReceiverType.getDynamicLowerBoundType().getClassType());
      if (refinedLowerBoundClass != null) {
        refinedLowerBound = refinedLowerBoundClass.asProgramClass();
        // TODO(b/154822960): Check if the lower bound is a subtype of the upper bound.
        if (refinedLowerBound != null && !isSubtype(refinedLowerBound.type, refinedReceiverType)) {
          refinedLowerBound = null;
        }
      }
    }
    LookupResultSuccess lookupResult =
        resolutionResult
            .lookupVirtualDispatchTargets(
                context.getHolder(),
                appView,
                refinedReceiverClass.asProgramClass(),
                refinedLowerBound)
            .asLookupResultSuccess();
    if (lookupResult != null && !lookupResult.isIncomplete()) {
      LookupTarget singleTarget = lookupResult.getSingleLookupTarget();
      if (singleTarget != null && singleTarget.isMethodTarget()) {
        singleMethodTarget = singleTarget.asMethodTarget().getTarget();
      }
    }
    if (!dynamicReceiverType.hasDynamicLowerBoundType()) {
      singleTargetLookupCache.addToCache(refinedReceiverType, method, singleMethodTarget);
    }
    return singleMethodTarget;
  }

  @SuppressWarnings("ReferenceEquality")
  private DispatchTargetLookupResult getMethodTargetFromExactRuntimeInformation(
      DexType refinedReceiverType,
      ClassTypeElement receiverLowerBoundType,
      SingleResolutionResult<?> resolution,
      DexClass refinedReceiverClass) {
    // If the lower-bound on the receiver type is the same as the upper-bound, then we have exact
    // runtime type information. In this case, the invoke will dispatch to the resolution result
    // from the runtime type of the receiver.
    if (receiverLowerBoundType != null
        && receiverLowerBoundType.getClassType() == refinedReceiverType) {
      if (refinedReceiverClass.isProgramClass()) {
        LookupMethodTarget methodTarget =
            resolution.lookupVirtualDispatchTarget(refinedReceiverClass.asProgramClass(), this);
        if (methodTarget == null
            || (methodTarget.getTarget().isProgramMethod()
                && !getKeepInfo()
                    .getMethodInfo(methodTarget.getTarget().asProgramMethod())
                    .isOptimizationAllowed(options()))) {
          // TODO(b/150640456): We should maybe only consider program methods.
          return new UnknownDispatchTargetLookupResult(resolution);
        }
        return new SingleDispatchTargetLookupResult(methodTarget.getTarget(), resolution);
      } else {
        // TODO(b/150640456): We should maybe only consider program methods.
        // If we resolved to a method on the refined receiver in the library, then we report the
        // method as a single target as well. This is a bit iffy since the library could change
        // implementation, but we use this for library modelling.
        DexClassAndMethod resolvedMethod = resolution.getResolutionPair();
        DexClassAndMethod targetOnReceiver =
            refinedReceiverClass.lookupVirtualClassMethod(resolvedMethod.getReference());
        if (targetOnReceiver != null && isOverriding(resolvedMethod, targetOnReceiver)) {
          return new SingleDispatchTargetLookupResult(targetOnReceiver, resolution);
        }
        return new UnknownDispatchTargetLookupResult(resolution);
      }
    }
    return null;
  }

  public AppInfoWithLiveness withSwitchMaps(Map<DexField, Int2ReferenceMap<DexField>> switchMaps) {
    assert checkIfObsolete();
    assert this.switchMaps.isEmpty();
    return new AppInfoWithLiveness(this, switchMaps);
  }

  /**
   * Visit all class definitions of classpath classes that are referenced in the compilation unit.
   *
   * <p>TODO(b/139464956): Only traverse the classpath types referenced from the live program.
   * Conservatively traces all classpath classes for now.
   */
  public void forEachReferencedClasspathClass(Consumer<DexClasspathClass> fn) {
    app().asDirect().classpathClasses().forEach(fn);
  }

  @Override
  public void forEachInstantiatedSubType(
      DexType type,
      Consumer<DexProgramClass> subTypeConsumer,
      Consumer<LambdaDescriptor> callSiteConsumer) {
    objectAllocationInfoCollection.forEachInstantiatedSubType(
        type, subTypeConsumer, callSiteConsumer, this);
  }

  public void forEachInstantiatedSubTypeInChain(
      DexProgramClass refinedReceiverUpperBound,
      DexProgramClass refinedReceiverLowerBound,
      Consumer<DexProgramClass> subTypeConsumer,
      Consumer<LambdaDescriptor> callSiteConsumer) {
    List<DexProgramClass> subTypes =
        computeProgramClassRelationChain(refinedReceiverLowerBound, refinedReceiverUpperBound);
    for (DexProgramClass subType : subTypes) {
      if (isInstantiatedOrPinned(subType)) {
        subTypeConsumer.accept(subType);
      }
    }
  }

  private boolean isInstantiatedOrPinned(DexProgramClass clazz) {
    return isInstantiatedDirectly(clazz) || isPinned(clazz) || isInstantiatedInterface(clazz);
  }

  public boolean isPinnedNotProgramOrLibraryOverride(DexDefinition definition) {
    if (isPinned(definition)) {
      return true;
    }
    if (definition.isDexEncodedMethod()) {
      DexEncodedMethod method = definition.asDexEncodedMethod();
      return !method.isProgramMethod(this) || method.isLibraryMethodOverride().isPossiblyTrue();
    }
    assert definition.isDexClass();
    DexClass clazz = definition.asDexClass();
    return clazz.isNotProgramClass() || isInstantiatedInterface(clazz.asProgramClass());
  }

  public boolean verifyNoIteratingOverPrunedClasses() {
    classes()
        .forEach(
            clazz -> {
              assert !wasPruned(clazz.type) : clazz.type + " was not pruned";
            });
    return true;
  }
}
