// Copyright (c) 2021, 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.ir.desugar.itf;

import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.cf.code.CfNew;
import com.android.tools.r8.cf.code.CfStackInstruction;
import com.android.tools.r8.cf.code.CfStackInstruction.Opcode;
import com.android.tools.r8.cf.code.CfThrow;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndMember;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexLibraryClass;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GenericSignature;
import com.android.tools.r8.graph.GenericSignature.ClassTypeSignature;
import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
import com.android.tools.r8.graph.LibraryMethod;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.MethodResolutionResult;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.position.MethodPosition;
import com.android.tools.r8.utils.BooleanBox;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.MethodSignatureEquivalence;
import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.WorkList;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import com.google.common.base.Equivalence.Wrapper;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableSet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import org.objectweb.asm.Opcodes;

/**
 * Default and static method interface desugaring processor for classes.
 *
 * <p>The core algorithm of the class processing is to ensure that for any type, all of its super
 * and implements hierarchy is computed first, and based on the summaries of these types the summary
 * of the class can be computed and the required forwarding methods on that type can be generated.
 * In other words, the traversal is in top-down (edges from type to its subtypes) topological order.
 * The traversal is lazy, starting from the unordered set of program classes.
 */
final class ClassProcessor implements InterfaceDesugaringProcessor {

  // Collection for method signatures that may cause forwarding methods to be created.
  private static class MethodSignatures {

    static final MethodSignatures EMPTY = new MethodSignatures(Collections.emptySet());

    static MethodSignatures create(Set<Wrapper<DexMethod>> signatures) {
      return signatures.isEmpty() ? EMPTY : new MethodSignatures(signatures);
    }

    final Set<Wrapper<DexMethod>> signatures;

    MethodSignatures(Set<Wrapper<DexMethod>> signatures) {
      this.signatures = Collections.unmodifiableSet(signatures);
    }

    MethodSignatures merge(MethodSignatures other) {
      if (isEmpty()) {
        return other;
      }
      if (other.isEmpty()) {
        return this;
      }
      Set<Wrapper<DexMethod>> merged = new HashSet<>(signatures);
      merged.addAll(other.signatures);
      return signatures.size() == merged.size() ? this : new MethodSignatures(merged);
    }

    boolean isEmpty() {
      return signatures.isEmpty();
    }

    public MethodSignatures withoutAll(MethodSignatures other) {
      Set<Wrapper<DexMethod>> merged = new HashSet<>(signatures);
      merged.removeAll(other.signatures);
      return signatures.size() == merged.size() ? this : new MethodSignatures(merged);
    }
  }

  // Collection of information known at the point of a given (non-library) class.
  // This info is immutable and shared as it is often the same on a significant part of the
  // class hierarchy. Thus, in the case of additions the parent pointer will contain prior info.
  private static class ClassInfo {

    static final ClassInfo EMPTY =
        new ClassInfo(null, ImmutableList.of(), EmulatedInterfaceInfo.EMPTY);

    final ClassInfo parent;

    // List of methods that are known to be forwarded to by a forwarding method at this point in the
    // class hierarchy. This set consists of the default interface methods, i.e., the targets of the
    // forwarding methods, *not* the forwarding methods themselves.
    final ImmutableList<DexClassAndMethod> forwardedMethodTargets;
    // If the forwarding methods for the emulated interface methods have not been added yet,
    // this contains the information to add it in the subclasses.
    final EmulatedInterfaceInfo emulatedInterfaceInfo;

    ClassInfo(
        ClassInfo parent,
        ImmutableList<DexClassAndMethod> forwardedMethodTargets,
        EmulatedInterfaceInfo emulatedInterfaceInfo) {
      this.parent = parent;
      this.forwardedMethodTargets = forwardedMethodTargets;
      this.emulatedInterfaceInfo = emulatedInterfaceInfo;
    }

    static ClassInfo create(
        ClassInfo parent,
        ImmutableList<DexClassAndMethod> forwardedMethodTargets,
        EmulatedInterfaceInfo emulatedInterfaceInfo) {
      return forwardedMethodTargets.isEmpty() && emulatedInterfaceInfo.isEmpty()
          ? parent
          : new ClassInfo(parent, forwardedMethodTargets, emulatedInterfaceInfo);
    }

    public boolean isEmpty() {
      return this == EMPTY;
    }

    boolean isTargetedByForwards(DexClassAndMethod method) {
      return IterableUtils.any(
              forwardedMethodTargets,
              DexClassAndMember::getDefinition,
              definition -> definition == method.getDefinition())
          || (parent != null && parent.isTargetedByForwards(method));
    }
  }

  // Collection of information on what signatures and what emulated interfaces require
  // forwarding methods for library classes and interfaces.
  private static class SignaturesInfo {

    static final SignaturesInfo EMPTY =
        new SignaturesInfo(MethodSignatures.EMPTY, EmulatedInterfaceInfo.EMPTY);

    final MethodSignatures signatures;
    final EmulatedInterfaceInfo emulatedInterfaceInfo;

    private SignaturesInfo(
        MethodSignatures methodsToForward, EmulatedInterfaceInfo emulatedInterfaceInfo) {
      this.signatures = methodsToForward;
      this.emulatedInterfaceInfo = emulatedInterfaceInfo;
    }

    public static SignaturesInfo create(MethodSignatures signatures) {
      if (signatures.isEmpty()) {
        return EMPTY;
      }
      return new SignaturesInfo(signatures, EmulatedInterfaceInfo.EMPTY);
    }

    public SignaturesInfo merge(SignaturesInfo other) {
      if (isEmpty()) {
        return other;
      }
      if (other.isEmpty()) {
        return this;
      }
      return new SignaturesInfo(
          signatures.merge(other.signatures),
          emulatedInterfaceInfo.merge(other.emulatedInterfaceInfo));
    }

    public MethodSignatures emulatedInterfaceSignaturesToForward() {
      return emulatedInterfaceInfo.signatures.withoutAll(signatures);
    }

    boolean isEmpty() {
      return signatures.isEmpty() && emulatedInterfaceInfo.isEmpty();
    }

    public SignaturesInfo withSignatures(MethodSignatures additions) {
      if (additions.isEmpty()) {
        return this;
      }
      MethodSignatures newSignatures = signatures.merge(additions);
      return new SignaturesInfo(newSignatures, emulatedInterfaceInfo);
    }

    public SignaturesInfo withEmulatedInterfaceInfo(
        EmulatedInterfaceInfo additionalEmulatedInterfaceInfo) {
      if (additionalEmulatedInterfaceInfo.isEmpty()) {
        return this;
      }
      return new SignaturesInfo(
          signatures, emulatedInterfaceInfo.merge(additionalEmulatedInterfaceInfo));
    }
  }

  // Emulated interfaces together with the generic signatures.
  static class EmulatedInterfaces {
    static EmulatedInterfaces EMPTY = new EmulatedInterfaces(ImmutableSet.of());

    final Set<DexType> emulatedInterfaces;

    EmulatedInterfaces(DexType emulatedInterface) {
      this.emulatedInterfaces = ImmutableSet.of(emulatedInterface);
    }

    private EmulatedInterfaces(Set<DexType> emulatedInterfaces) {
      this.emulatedInterfaces = emulatedInterfaces;
    }

    boolean isEmpty() {
      return emulatedInterfaces.isEmpty();
    }

    boolean contains(DexType type) {
      return emulatedInterfaces.contains(type);
    }

    Set<DexType> getEmulatedInterfaces() {
      return emulatedInterfaces;
    }

    EmulatedInterfaces merge(EmulatedInterfaces other) {
      ImmutableSet.Builder<DexType> newEmulatedInterfaces = ImmutableSet.builder();
      newEmulatedInterfaces.addAll(emulatedInterfaces);
      newEmulatedInterfaces.addAll(other.emulatedInterfaces);
      return new EmulatedInterfaces(newEmulatedInterfaces.build());
    }
  }

  // List of emulated interfaces and corresponding signatures which may require forwarding methods.
  // If one of the signatures has an override, then the class holding the override is required to
  // add the forwarding methods for all signatures, and introduce the corresponding emulated
  // interface in its interfaces attribute for correct emulated dispatch.
  // If no override is present, then no forwarding methods are required, the class relies on the
  // default behavior of the emulated dispatch.
  private static class EmulatedInterfaceInfo {

    static final EmulatedInterfaceInfo EMPTY =
        new EmulatedInterfaceInfo(MethodSignatures.EMPTY, EmulatedInterfaces.EMPTY);

    final MethodSignatures signatures;
    final EmulatedInterfaces emulatedInterfaces;

    private EmulatedInterfaceInfo(
        MethodSignatures methodsToForward, EmulatedInterfaces emulatedInterfaces) {
      this.signatures = methodsToForward;
      this.emulatedInterfaces = emulatedInterfaces;
    }

    public EmulatedInterfaceInfo merge(EmulatedInterfaceInfo other) {
      if (isEmpty()) {
        return other;
      }
      if (other.isEmpty()) {
        return this;
      }
      return new EmulatedInterfaceInfo(
          signatures.merge(other.signatures), emulatedInterfaces.merge(other.emulatedInterfaces));
    }

    public boolean isEmpty() {
      assert !emulatedInterfaces.isEmpty() || signatures.isEmpty();
      return emulatedInterfaces.isEmpty();
    }

    boolean contains(DexType type) {
      return emulatedInterfaces.contains(type);
    }
  }

  // Helper to keep track of the direct active subclass and nearest program subclass for reporting.
  private static class ReportingContext {

    final DexClass directSubClass;
    final DexProgramClass closestProgramSubClass;

    public ReportingContext(DexClass directSubClass, DexProgramClass closestProgramSubClass) {
      this.directSubClass = directSubClass;
      this.closestProgramSubClass = closestProgramSubClass;
    }

    ReportingContext forClass(DexClass directSubClass) {
      return new ReportingContext(
          directSubClass,
          directSubClass.isProgramClass()
              ? directSubClass.asProgramClass()
              : closestProgramSubClass);
    }

    public DexClass definitionFor(DexType type, AppView<?> appView) {
      return appView.appInfo().definitionForDesugarDependency(directSubClass, type);
    }

    public void reportMissingType(DexType missingType, InterfaceDesugaringSyntheticHelper helper) {
      helper.warnMissingInterface(closestProgramSubClass, closestProgramSubClass, missingType);
    }
  }

  // Specialized context to disable reporting when traversing the library structure.
  private static class LibraryReportingContext extends ReportingContext {

    static final LibraryReportingContext LIBRARY_CONTEXT = new LibraryReportingContext();

    LibraryReportingContext() {
      super(null, null);
    }

    @Override
    ReportingContext forClass(DexClass directSubClass) {
      return this;
    }

    @Override
    public DexClass definitionFor(DexType type, AppView<?> appView) {
      return appView.definitionFor(type);
    }

    @Override
    public void reportMissingType(DexType missingType, InterfaceDesugaringSyntheticHelper helper) {
      // Ignore missing types in the library.
    }
  }

  private final AppView<?> appView;
  private final DexItemFactory dexItemFactory;
  private final InterfaceDesugaringSyntheticHelper helper;
  private final MethodSignatureEquivalence equivalence = MethodSignatureEquivalence.get();
  private final boolean needsLibraryInfo;
  private final Predicate<ProgramMethod> isLiveMethod;

  // Mapping from program and classpath classes to their information summary.
  private final Map<DexClass, ClassInfo> classInfo = new ConcurrentHashMap<>();

  // Mapping from library classes to their information summary.
  private final Map<DexLibraryClass, SignaturesInfo> libraryClassInfo = new ConcurrentHashMap<>();

  // Mapping from arbitrary interfaces to an information summary.
  private final Map<DexClass, SignaturesInfo> interfaceInfo = new ConcurrentHashMap<>();

  // Mapping from actual program classes to the synthesized forwarding methods to be created.
  private final Map<DexProgramClass, ProgramMethodSet> newSyntheticMethods =
      new ConcurrentHashMap<>();

  // Mapping from actual program classes to the extra interfaces needed for emulated dispatch.
  private final Map<DexProgramClass, List<ClassTypeSignature>> newExtraInterfaceSignatures =
      new ConcurrentHashMap<>();

  ClassProcessor(AppView<?> appView, Predicate<ProgramMethod> isLiveMethod) {
    this.appView = appView;
    this.dexItemFactory = appView.dexItemFactory();
    this.helper = new InterfaceDesugaringSyntheticHelper(appView);
    needsLibraryInfo =
        !appView.options().desugaredLibraryConfiguration.getEmulateLibraryInterface().isEmpty()
            || !appView
                .options()
                .desugaredLibraryConfiguration
                .getRetargetCoreLibMember()
                .isEmpty();
    this.isLiveMethod = isLiveMethod;
  }

  private boolean isLiveMethod(DexClassAndMethod method) {
    if (method.isProgramMethod()) {
      return isLiveMethod.test(method.asProgramMethod());
    }
    return true;
  }

  private boolean needsLibraryInfo() {
    return needsLibraryInfo;
  }

  private boolean ignoreLibraryInfo() {
    return !needsLibraryInfo;
  }

  @Override
  public void process(
      DexProgramClass clazz, InterfaceProcessingDesugaringEventConsumer eventConsumer) {
    if (!clazz.isInterface()) {
      visitClassInfo(clazz, new ReportingContext(clazz, clazz));
    }
  }

  // We introduce forwarding methods only once all desugaring has been performed to avoid
  // confusing the look-up with inserted forwarding methods.
  @Override
  public final void finalizeProcessing(InterfaceProcessingDesugaringEventConsumer eventConsumer) {
    newSyntheticMethods.forEach(
        (clazz, newForwardingMethods) -> {
          clazz.addVirtualMethods(newForwardingMethods.toDefinitionSet());
          newForwardingMethods.forEach(eventConsumer::acceptForwardingMethod);
        });
    newExtraInterfaceSignatures.forEach(
        (clazz, extraInterfaceSignatures) -> {
          if (!extraInterfaceSignatures.isEmpty()) {
            for (ClassTypeSignature signature : extraInterfaceSignatures) {
              eventConsumer.acceptEmulatedInterfaceMarkerInterface(
                  clazz, helper.ensureEmulatedInterfaceMarkerInterface(signature.type()));
            }
            clazz.addExtraInterfaces(extraInterfaceSignatures);
          }
        });
  }

  // Computes the set of method signatures that may need forwarding methods on derived classes.
  private SignaturesInfo computeInterfaceInfo(DexClass iface, SignaturesInfo interfaceInfo) {
    assert iface.isInterface();
    assert iface.superType == dexItemFactory.objectType;
    assert !helper.isEmulatedInterface(iface.type);
    // Add non-library default methods as well as those for desugared library classes.
    if (!iface.isLibraryClass() || (needsLibraryInfo() && helper.isInDesugaredLibrary(iface))) {
      MethodSignatures signatures = getDefaultMethods(iface);
      interfaceInfo = interfaceInfo.withSignatures(signatures);
    }
    return interfaceInfo;
  }

  private SignaturesInfo computeEmulatedInterfaceInfo(
      DexClass iface, SignaturesInfo interfaceInfo) {
    assert iface.isInterface();
    assert iface.superType == dexItemFactory.objectType;
    assert helper.isEmulatedInterface(iface.type);
    assert needsLibraryInfo();
    MethodSignatures signatures = getDefaultMethods(iface);
    EmulatedInterfaceInfo emulatedInterfaceInfo =
        new EmulatedInterfaceInfo(signatures, new EmulatedInterfaces(iface.type));
    return interfaceInfo.withEmulatedInterfaceInfo(emulatedInterfaceInfo);
  }

  private MethodSignatures getDefaultMethods(DexClass iface) {
    assert iface.isInterface();
    Set<Wrapper<DexMethod>> defaultMethods =
        new HashSet<>(iface.getMethodCollection().numberOfVirtualMethods());
    for (DexEncodedMethod method : iface.virtualMethods(DexEncodedMethod::isDefaultMethod)) {
      defaultMethods.add(equivalence.wrap(method.getReference()));
    }
    return MethodSignatures.create(defaultMethods);
  }

  // Computes the set of signatures of that may need forwarding methods on classes that derive
  // from a library class.
  private SignaturesInfo computeLibraryClassInfo(DexLibraryClass clazz, SignaturesInfo signatures) {
    // The result is the identity as the library class does not itself contribute to the set.
    return signatures;
  }

  // The computation of a class information and the insertions of forwarding methods.
  private ClassInfo computeClassInfo(
      DexClass clazz, ClassInfo superInfo, SignaturesInfo signatureInfo) {
    ImmutableList.Builder<DexClassAndMethod> additionalForwards = ImmutableList.builder();
    // First we deal with non-emulated interface desugaring.
    resolveForwardingMethods(clazz, superInfo, signatureInfo.signatures, additionalForwards);
    // Second we deal with emulated interface, if one method has override in the current class,
    // we resolve them, else we propagate the emulated interface info down.
    if (shouldResolveForwardingMethodsForEmulatedInterfaces(
        clazz, signatureInfo.emulatedInterfaceInfo)) {
      resolveForwardingMethods(
          clazz,
          superInfo,
          signatureInfo.emulatedInterfaceSignaturesToForward(),
          additionalForwards);
      duplicateEmulatedInterfaces(clazz, signatureInfo.emulatedInterfaceInfo.emulatedInterfaces);
      return ClassInfo.create(superInfo, additionalForwards.build(), EmulatedInterfaceInfo.EMPTY);
    }
    return ClassInfo.create(
        superInfo, additionalForwards.build(), signatureInfo.emulatedInterfaceInfo);
  }

  // All classes implementing an emulated interface and overriding a default method should now
  // implement the interface and the emulated one for correct emulated dispatch.
  // The class signature won't include the correct type parameters for the duplicated interfaces,
  // i.e., there will be foo.A instead of foo.A<K,V>, but such parameters are unused.
  private void duplicateEmulatedInterfaces(DexClass clazz, EmulatedInterfaces emulatedInterfaces) {
    if (clazz.isNotProgramClass()) {
      return;
    }
    Set<DexType> filtered = new HashSet<>(emulatedInterfaces.getEmulatedInterfaces());
    WorkList<DexType> workList = WorkList.newIdentityWorkList();
    for (DexType emulatedInterface : emulatedInterfaces.getEmulatedInterfaces()) {
      DexClass iface = appView.definitionFor(emulatedInterface);
      if (iface != null) {
        assert iface.isLibraryClass()
            || appView.options().desugaredLibraryConfiguration.isLibraryCompilation();
        workList.addIfNotSeen(iface.getInterfaces());
      }
    }
    while (workList.hasNext()) {
      DexType type = workList.next();
      filtered.remove(type);
      DexClass iface = appView.definitionFor(type);
      if (iface == null) {
        continue;
      }
      workList.addIfNotSeen(iface.getInterfaces());
    }

    for (DexType emulatedInterface : emulatedInterfaces.getEmulatedInterfaces()) {
      DexClass s = appView.definitionFor(emulatedInterface);
      if (s != null) {
        s = appView.definitionFor(s.superType);
      }
      while (s != null && s.getType() != appView.dexItemFactory().objectType) {
        filtered.remove(s.getType());
        s = appView.definitionFor(s.getSuperType());
      }
    }

    // Collect the signatures for the emulated interfaces to add.
    Map<DexType, GenericSignature.ClassTypeSignature> signatures = new IdentityHashMap<>();
    collectEmulatedInterfaces(clazz, filtered, signatures);
    // We need to introduce them in deterministic order for deterministic compilation.
    ArrayList<DexType> sortedEmulatedInterfaces = new ArrayList<>(filtered);
    Collections.sort(sortedEmulatedInterfaces);
    List<GenericSignature.ClassTypeSignature> extraInterfaceSignatures = new ArrayList<>();
    for (DexType extraInterface : sortedEmulatedInterfaces) {
      GenericSignature.ClassTypeSignature signature = signatures.get(extraInterface);
      assert signature != null;
      extraInterfaceSignatures.add(signature);
    }
    // The emulated interface might already be implemented if the input class has gone through
    // library desugaring already.
    clazz
        .getInterfaces()
        .forEach(
            iface -> {
              for (int i = 0; i < extraInterfaceSignatures.size(); i++) {
                if (extraInterfaceSignatures.get(i).type() == iface) {
                  if (!appView.options().desugarSpecificOptions().allowAllDesugaredInput) {
                    throw new CompilationError(
                        "Code has already been library desugared. Interface "
                            + iface.getDescriptor()
                            + " is already implemented by "
                            + clazz.getType().getDescriptor());
                  }
                  extraInterfaceSignatures.remove(i);
                  break;
                }
              }
            });
    newExtraInterfaceSignatures.put(clazz.asProgramClass(), extraInterfaceSignatures);
  }

  private void collectEmulatedInterfaces(
      DexClass clazz,
      Set<DexType> emulatesInterfaces,
      Map<DexType, GenericSignature.ClassTypeSignature> extraInterfaceSignatures) {
    // TODO(b/182329331): Only handle type arguments for Cf to Cf desugar.
    if (appView.options().cfToCfDesugar && clazz.validInterfaceSignatures()) {
      clazz.forEachImmediateSupertype(
          (type, signature) -> {
            if (emulatesInterfaces.contains(type)) {
              extraInterfaceSignatures.put(
                  type,
                  new GenericSignature.ClassTypeSignature(
                      helper.getEmulatedInterface(type), signature.typeArguments()));
            }
            collectEmulatedInterfacesWithPropagatedTypeArguments(
                type, signature.typeArguments(), emulatesInterfaces, extraInterfaceSignatures);
          });
    } else {
      clazz.forEachImmediateSupertype(
          (type) -> {
            if (emulatesInterfaces.contains(type)) {
              extraInterfaceSignatures.put(
                  type, new GenericSignature.ClassTypeSignature(helper.getEmulatedInterface(type)));
            }
            collectEmulatedInterfacesWithPropagatedTypeArguments(
                type, null, emulatesInterfaces, extraInterfaceSignatures);
          });
    }
  }

  private void collectEmulatedInterfacesWithPropagatedTypeArguments(
      DexType type,
      List<GenericSignature.FieldTypeSignature> typeArguments,
      Set<DexType> emulatesInterfaces,
      Map<DexType, GenericSignature.ClassTypeSignature> extraInterfaceSignatures) {
    DexClass clazz = appView.definitionFor(type);
    if (clazz == null) {
      return;
    }
    // TODO(b/182329331): Only handle type arguments for Cf to Cf desugar.
    if (appView.options().cfToCfDesugar && clazz.validInterfaceSignatures()) {
      assert typeArguments != null;
      clazz.forEachImmediateSupertypeWithAppliedTypeArguments(
          typeArguments,
          (iface, signature) -> {
            if (emulatesInterfaces.contains(iface)) {
              extraInterfaceSignatures.put(
                  iface,
                  new GenericSignature.ClassTypeSignature(
                      helper.getEmulatedInterface(iface), signature));
            }
            collectEmulatedInterfacesWithPropagatedTypeArguments(
                iface, signature, emulatesInterfaces, extraInterfaceSignatures);
          });
    } else {
      assert typeArguments == null;
      clazz.forEachImmediateSupertype(
          iface -> {
            if (emulatesInterfaces.contains(iface)) {
              extraInterfaceSignatures.put(
                  iface,
                  new GenericSignature.ClassTypeSignature(helper.getEmulatedInterface(iface)));
            }
            collectEmulatedInterfacesWithPropagatedTypeArguments(
                iface, null, emulatesInterfaces, extraInterfaceSignatures);
          });
    }
  }
  // If any of the signature would lead to a different behavior than the default method on the
  // emulated interface, we need to resolve the forwarding methods.
  private boolean shouldResolveForwardingMethodsForEmulatedInterfaces(
      DexClass clazz, EmulatedInterfaceInfo emulatedInterfaceInfo) {
    AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
    for (Wrapper<DexMethod> signature : emulatedInterfaceInfo.signatures.signatures) {
      MethodResolutionResult resolutionResult =
          appInfo.resolveMethodOnClass(signature.get(), clazz);
      if (resolutionResult.isFailedResolution()) {
        return true;
      }
      DexClass resolvedHolder = resolutionResult.asSingleResolution().getResolvedHolder();
      if (!resolvedHolder.isLibraryClass()
          && !emulatedInterfaceInfo.contains(resolvedHolder.type)) {
        return true;
      }
    }
    return false;
  }

  private void resolveForwardingMethods(
      DexClass clazz,
      ClassInfo superInfo,
      MethodSignatures signatures,
      Builder<DexClassAndMethod> additionalForwards) {
    if (clazz.isProgramClass() && appView.isAlreadyLibraryDesugared(clazz.asProgramClass())) {
      return;
    }
    for (Wrapper<DexMethod> wrapper : signatures.signatures) {
      resolveForwardForSignature(
          clazz,
          wrapper.get(),
          target -> {
            if (isLiveMethod(target) && !superInfo.isTargetedByForwards(target)) {
              additionalForwards.add(target);
              addForwardingMethod(target, clazz);
            }
          });
    }
  }

  // Looks up a method signature from the point of 'clazz', if it can dispatch to a default method
  // the 'addForward' call-back is called with the target of the forward.
  private void resolveForwardForSignature(
      DexClass clazz, DexMethod method, Consumer<DexClassAndMethod> addForward) {
    AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
    MethodResolutionResult resolutionResult = appInfo.resolveMethodOn(clazz, method);
    if (resolutionResult.isFailedResolution()
        || resolutionResult.asSuccessfulMemberResolutionResult().getResolvedMember().isStatic()) {
      // When doing resolution we may find a static or private targets and bubble up the failed
      // resolution to preserve ICCE even though the resolution actually succeeded, ie. finding a
      // method with the same name and descriptor. For invoke-virtual and invoke-interface, the
      // selected method will only consider instance methods.
      BooleanBox staticTarget = new BooleanBox(true);
      if (resolutionResult.isFailedResolution()) {
        resolutionResult
            .asFailedResolution()
            .forEachFailureDependency(target -> staticTarget.and(target.isStatic()));
      } else if (resolutionResult.isSuccessfulMemberResolutionResult()) {
        staticTarget.set(
            resolutionResult.asSuccessfulMemberResolutionResult().getResolvedMember().isStatic());
      }
      if (staticTarget.isAssigned() && staticTarget.isTrue()) {
        resolutionResult = appInfo.resolveMethodOnInterface(method.holder, method);
      }
      if (resolutionResult.isFailedResolution()) {
        if (resolutionResult.isIncompatibleClassChangeErrorResult()) {
          addICCEThrowingMethod(method, clazz);
          return;
        }
        if (resolutionResult.isNoSuchMethodErrorResult(clazz, appInfo)) {
          addNoSuchMethodErrorThrowingMethod(method, clazz);
          return;
        }
        assert resolutionResult.isIllegalAccessErrorResult(clazz, appInfo);
        addIllegalAccessErrorThrowingMethod(method, clazz);
        return;
      }
    }
    assert resolutionResult.isSuccessfulMemberResolutionResult();
    DexClassAndMethod virtualDispatchTarget =
        resolutionResult.lookupVirtualDispatchTarget(clazz, appInfo);
    assert virtualDispatchTarget != null;

    // Don't forward if the target is explicitly marked as 'dont-rewrite'
    if (dontRewrite(virtualDispatchTarget)) {
      return;
    }

    // If resolution targets a default interface method, forward it.
    if (virtualDispatchTarget.isDefaultMethod()) {
      addForward.accept(virtualDispatchTarget);
      return;
    }

    // Remaining edge cases only pertain to desugaring of library methods.
    if (!virtualDispatchTarget.isLibraryMethod() || ignoreLibraryInfo()) {
      return;
    }

    LibraryMethod libraryMethod = virtualDispatchTarget.asLibraryMethod();
    if (isRetargetMethod(libraryMethod)) {
      addForward.accept(virtualDispatchTarget);
      return;
    }

    // If target is a non-interface library class it may be an emulated interface,
    // except on a rewritten type, where L8 has already dealt with the desugaring.
    if (!libraryMethod.getHolder().isInterface()
        && !appView.rewritePrefix.hasRewrittenType(libraryMethod.getHolderType(), appView)) {
      // Here we use step-3 of resolution to find a maximally specific default interface method.
      DexClassAndMethod result =
          appInfo.lookupMaximallySpecificMethod(libraryMethod.getHolder(), method);
      if (result != null && helper.isEmulatedInterface(result.getHolderType())) {
        addForward.accept(result);
      }
    }
  }

  private boolean isRetargetMethod(LibraryMethod method) {
    assert needsLibraryInfo();
    assert method.getDefinition().isNonPrivateVirtualMethod();
    return !method.getAccessFlags().isFinal()
        && appView.options().desugaredLibraryConfiguration.retargetMethod(method, appView) != null;
  }

  private boolean dontRewrite(DexClassAndMethod method) {
    return needsLibraryInfo() && method.getHolder().isLibraryClass() && helper.dontRewrite(method);
  }

  // Construction of actual forwarding methods.

  private void addSyntheticMethod(DexProgramClass clazz, DexEncodedMethod method) {
    newSyntheticMethods
        .computeIfAbsent(clazz, key -> ProgramMethodSet.create())
        .createAndAdd(clazz, method);
  }

  private void addICCEThrowingMethod(DexMethod method, DexClass clazz) {
    addThrowingMethod(method, clazz, dexItemFactory.icceType);
  }

  private void addIllegalAccessErrorThrowingMethod(DexMethod method, DexClass clazz) {
    addThrowingMethod(method, clazz, dexItemFactory.illegalAccessErrorType);
  }

  private void addNoSuchMethodErrorThrowingMethod(DexMethod method, DexClass clazz) {
    addThrowingMethod(method, clazz, dexItemFactory.noSuchMethodErrorType);
  }

  private void addThrowingMethod(DexMethod method, DexClass clazz, DexType errorType) {
    if (!clazz.isProgramClass()) {
      return;
    }
    MethodAccessFlags accessFlags = MethodAccessFlags.builder().setPublic().build();
    DexMethod newMethod = method.withHolder(clazz.getType(), dexItemFactory);
    DexEncodedMethod newEncodedMethod =
        new DexEncodedMethod(
            newMethod,
            accessFlags,
            MethodTypeSignature.noSignature(),
            DexAnnotationSet.empty(),
            ParameterAnnotationsList.empty(),
            createExceptionThrowingCfCode(newMethod, accessFlags, errorType, dexItemFactory),
            true);
    addSyntheticMethod(clazz.asProgramClass(), newEncodedMethod);
  }

  private static CfCode createExceptionThrowingCfCode(
      DexMethod method,
      MethodAccessFlags accessFlags,
      DexType exceptionType,
      DexItemFactory dexItemFactory) {
    DexMethod instanceInitializer =
        dexItemFactory.createMethod(
            exceptionType,
            dexItemFactory.createProto(dexItemFactory.voidType),
            dexItemFactory.constructorMethodName);
    int maxStack = 2;
    int maxLocals = method.getParameters().size() + BooleanUtils.intValue(!accessFlags.isStatic());
    return new CfCode(
        method.getHolderType(),
        maxStack,
        maxLocals,
        ImmutableList.of(
            new CfNew(exceptionType),
            new CfStackInstruction(Opcode.Dup),
            new CfInvoke(Opcodes.INVOKESPECIAL, instanceInitializer, false),
            new CfThrow()));
  }

  // Note: The parameter 'target' may be a public method on a class in case of desugared
  // library retargeting (See below target.isInterface check).
  private void addForwardingMethod(DexClassAndMethod target, DexClass clazz) {
    if (!clazz.isProgramClass()) {
      return;
    }

    DexEncodedMethod methodOnSelf = clazz.lookupMethod(target.getReference());
    if (methodOnSelf != null) {
      throw new CompilationError(
          "Attempt to add forwarding method that conflicts with existing method.",
          null,
          clazz.getOrigin(),
          new MethodPosition(methodOnSelf.getReference().asMethodReference()));
    }

    // NOTE: Never add a forwarding method to methods of classes unknown or coming from android.jar
    // even if this results in invalid code, these classes are never desugared.
    // In desugared library, emulated interface methods can be overridden by retarget lib members.
    DexMethod forwardMethod =
        target.getHolder().isInterface()
            ? helper.ensureDefaultAsMethodOfCompanionClassStub(target).getReference()
            : appView.options().desugaredLibraryConfiguration.retargetMethod(target, appView);
    DexEncodedMethod desugaringForwardingMethod =
        DexEncodedMethod.createDesugaringForwardingMethod(
            target, clazz, forwardMethod, dexItemFactory);
    if (!target.isProgramDefinition()
        || target.getDefinition().isLibraryMethodOverride().isTrue()) {
      desugaringForwardingMethod.setLibraryMethodOverride(OptionalBool.TRUE);
    }
    addSyntheticMethod(clazz.asProgramClass(), desugaringForwardingMethod);
  }

  // Topological order traversal and its helpers.

  private DexClass definitionOrNull(DexType type, ReportingContext context) {
    // No forwards at the top of the class hierarchy (assuming java.lang.Object is never amended).
    if (type == null || type == dexItemFactory.objectType) {
      return null;
    }
    DexClass clazz = context.definitionFor(type, appView);
    if (clazz == null) {
      context.reportMissingType(type, helper);
      return null;
    }
    return clazz;
  }

  // We cannot use ConcurrentHashMap computeIfAbsent because the calls are recursive ending in
  // concurrent modification of the ConcurrentHashMap while performing computeIfAbsent.
  private <C extends DexClass, I> I reentrantComputeIfAbsent(
      Map<C, I> infoMap, C clazz, Function<C, I> supplier) {
    // Try to avoid the synchronization when possible.
    I computedInfo = infoMap.get(clazz);
    if (computedInfo != null) {
      return computedInfo;
    }
    synchronized (clazz) {
      computedInfo = infoMap.get(clazz);
      if (computedInfo != null) {
        return computedInfo;
      }
      computedInfo = supplier.apply(clazz);
      infoMap.put(clazz, computedInfo);
      return computedInfo;
    }
  }

  private ClassInfo visitClassInfo(DexType type, ReportingContext context) {
    DexClass clazz = definitionOrNull(type, context);
    return clazz == null ? ClassInfo.EMPTY : visitClassInfo(clazz, context);
  }

  private ClassInfo visitClassInfo(DexClass clazz, ReportingContext context) {
    assert !clazz.isInterface();
    if (clazz.isLibraryClass()) {
      return ClassInfo.EMPTY;
    }
    return reentrantComputeIfAbsent(classInfo, clazz, key -> visitClassInfoRaw(key, context));
  }

  private ClassInfo visitClassInfoRaw(DexClass clazz, ReportingContext context) {
    // We compute both library and class information, but one of them is empty, since a class is
    // a library class or is not, but cannot be both.
    ReportingContext thisContext = context.forClass(clazz);
    ClassInfo superInfo = visitClassInfo(clazz.superType, thisContext);
    SignaturesInfo signatures = visitLibraryClassInfo(clazz.superType);
    // The class may inherit emulated interface info from its program superclass if the latter
    // did not require to resolve the forwarding methods for emualted interfaces.
    assert superInfo.isEmpty() || signatures.isEmpty();
    signatures = signatures.withEmulatedInterfaceInfo(superInfo.emulatedInterfaceInfo);
    for (DexType iface : clazz.interfaces.values) {
      signatures = signatures.merge(visitInterfaceInfo(iface, thisContext));
    }
    return computeClassInfo(clazz, superInfo, signatures);
  }

  private SignaturesInfo visitLibraryClassInfo(DexType type) {
    // No desugaring required, no library class analysis.
    if (ignoreLibraryInfo()) {
      return SignaturesInfo.EMPTY;
    }
    DexClass clazz = definitionOrNull(type, LibraryReportingContext.LIBRARY_CONTEXT);
    return clazz == null ? SignaturesInfo.EMPTY : visitLibraryClassInfo(clazz);
  }

  private SignaturesInfo visitLibraryClassInfo(DexClass clazz) {
    assert !clazz.isInterface();
    return clazz.isLibraryClass()
        ? reentrantComputeIfAbsent(
            libraryClassInfo, clazz.asLibraryClass(), this::visitLibraryClassInfoRaw)
        : SignaturesInfo.EMPTY;
  }

  private SignaturesInfo visitLibraryClassInfoRaw(DexLibraryClass clazz) {
    SignaturesInfo signatures = visitLibraryClassInfo(clazz.superType);
    for (DexType iface : clazz.interfaces.values) {
      signatures =
          signatures.merge(visitInterfaceInfo(iface, LibraryReportingContext.LIBRARY_CONTEXT));
    }
    return computeLibraryClassInfo(clazz, signatures);
  }

  private SignaturesInfo visitInterfaceInfo(DexType iface, ReportingContext context) {
    DexClass definition = definitionOrNull(iface, context);
    return definition == null ? SignaturesInfo.EMPTY : visitInterfaceInfo(definition, context);
  }

  private SignaturesInfo visitInterfaceInfo(DexClass iface, ReportingContext context) {
    if (iface.isLibraryClass() && ignoreLibraryInfo()) {
      return SignaturesInfo.EMPTY;
    }
    return reentrantComputeIfAbsent(
        interfaceInfo, iface, key -> visitInterfaceInfoRaw(key, context));
  }

  private SignaturesInfo visitInterfaceInfoRaw(DexClass iface, ReportingContext context) {
    ReportingContext thisContext = context.forClass(iface);
    SignaturesInfo interfaceInfo = SignaturesInfo.EMPTY;
    for (DexType superiface : iface.interfaces.values) {
      interfaceInfo = interfaceInfo.merge(visitInterfaceInfo(superiface, thisContext));
    }
    return helper.isEmulatedInterface(iface.type)
        ? computeEmulatedInterfaceInfo(iface, interfaceInfo)
        : computeInterfaceInfo(iface, interfaceInfo);
  }
}
