fix
diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
index 5904f98..33dbae6 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -136,8 +136,8 @@
   }
 
   @Override
-  public void collectIndexedItems(IndexedItemCollection indexedItems,
-      DexMethod method, int instructionOffset) {
+  public void collectIndexedItems(
+      IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
     if (indexedItems.addClass(this)) {
       type.collectIndexedItems(indexedItems, method, instructionOffset);
       if (superType != null) {
@@ -167,8 +167,8 @@
     }
   }
 
-  private static <T extends DexItem> void synchronizedCollectAll(IndexedItemCollection collection,
-      T[] items) {
+  private static <T extends DexItem> void synchronizedCollectAll(
+      IndexedItemCollection collection, T[] items) {
     synchronized (items) {
       collectAll(collection, items);
     }
@@ -418,6 +418,50 @@
     }
   }
 
+  public void addExtraInterfaces(List<DexType> extraInterfaces, DexItemFactory factory) {
+    if (extraInterfaces.isEmpty()) {
+      return;
+    }
+    addExtraInterfacesToInterfacesArray(extraInterfaces);
+    addExtraInterfacesToSignatureAnnotationIfPresent(extraInterfaces, factory);
+  }
+
+  private void addExtraInterfacesToInterfacesArray(List<DexType> extraInterfaces) {
+    DexType[] newInterfaces =
+        Arrays.copyOf(interfaces.values, interfaces.size() + extraInterfaces.size());
+    for (int i = interfaces.size(); i < newInterfaces.length; i++) {
+      newInterfaces[i] = extraInterfaces.get(i - interfaces.size());
+    }
+    interfaces = new DexTypeList(newInterfaces);
+  }
+
+  private void addExtraInterfacesToSignatureAnnotationIfPresent(
+      List<DexType> extraInterfaces, DexItemFactory factory) {
+    // We need to introduce in the dalvik.annotation.Signature annotation the extra interfaces.
+    // At this point we cheat and pretend the extraInterfaces simply don't use any generic types.
+    DexAnnotation[] annotations = annotations().annotations;
+    for (int i = 0; i < annotations.length; i++) {
+      DexAnnotation annotation = annotations[i];
+      if (DexAnnotation.isSignatureAnnotation(annotation, factory)) {
+        DexAnnotation[] rewrittenAnnotations = annotations.clone();
+        rewrittenAnnotations[i] = rewriteSignatureAnnotation(annotation, extraInterfaces, factory);
+        setAnnotations(new DexAnnotationSet(rewrittenAnnotations));
+        // There is at most one signature annotation, so we can return here.
+        return;
+      }
+    }
+  }
+
+  private DexAnnotation rewriteSignatureAnnotation(
+      DexAnnotation annotation, List<DexType> extraInterfaces, DexItemFactory factory) {
+    String signature = DexAnnotation.getSignature(annotation);
+    StringBuilder newSignatureBuilder = new StringBuilder(signature);
+    for (DexType extraInterface : extraInterfaces) {
+      newSignatureBuilder.append(extraInterface.descriptor.toString());
+    }
+    return DexAnnotation.createSignatureAnnotation(newSignatureBuilder.toString(), factory);
+  }
+
   @Override
   public DexProgramClass get() {
     return this;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index 58e87dd..9fea90b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -56,7 +56,6 @@
 import com.google.common.collect.Sets;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.IdentityHashMap;
@@ -333,10 +332,9 @@
     // applies up to 24.
     List<DexEncodedMethod> newForwardingMethods = new ArrayList<>();
     for (DexMethod dexMethod : dexMethods) {
-      DexType[] newInterfaces = Arrays.copyOf(clazz.interfaces.values, clazz.interfaces.size() + 1);
-      newInterfaces[newInterfaces.length - 1] =
-          BackportedMethodRewriter.dispatchInterfaceTypeFor(appView, dexMethod);
-      clazz.interfaces = new DexTypeList(newInterfaces);
+      clazz.addExtraInterfaces(
+          Collections.singletonList(dispatchInterfaceTypeFor(appView, dexMethod)),
+          appView.dexItemFactory());
       DexEncodedMethod dexEncodedMethod = clazz.lookupVirtualMethod(dexMethod);
       if (dexEncodedMethod == null) {
         DexEncodedMethod newMethod = createForwardingMethod(dexMethod, clazz);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
new file mode 100644
index 0000000..5ce5bb8
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
@@ -0,0 +1,483 @@
+// Copyright (c) 2020, 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;
+
+import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.ClassAccessFlags;
+import com.android.tools.r8.graph.DexAnnotationSet;
+import com.android.tools.r8.graph.DexApplication;
+import com.android.tools.r8.graph.DexClass;
+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.DexProto;
+import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodAccessFlags;
+import com.android.tools.r8.graph.ParameterAnnotationsList;
+import com.android.tools.r8.graph.ResolutionResult;
+import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.InstructionListIterator;
+import com.android.tools.r8.ir.code.InvokeMethod;
+import com.android.tools.r8.ir.code.InvokeStatic;
+import com.android.tools.r8.ir.conversion.IRConverter;
+import com.android.tools.r8.utils.StringDiagnostic;
+import com.android.tools.r8.utils.collections.SortedProgramMethodSet;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.IdentityHashMap;
+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;
+
+public class DesugaredLibraryRetargeter {
+
+  public static final String DESUGAR_LIB_RETARGET_CLASS_NAME_PREFIX =
+      "$r8$retargetLibraryMember$virtualDispatch";
+
+  private final AppView<?> appView;
+  private final Map<DexMethod, DexMethod> retargetLibraryMember = new IdentityHashMap<>();
+  // Map nonFinalRewrite hold a methodName -> method mapping for methods which are rewritten while
+  // the holder is non final. In this case d8 needs to force resolution of given methods to see if
+  // the invoke needs to be rewritten.
+  private final Map<DexString, List<DexMethod>> nonFinalHolderRewrites = new IdentityHashMap<>();
+  // Non final virtual library methods requiring generation of emulated dispatch.
+  private final Set<DexEncodedMethod> emulatedDispatchMethods = Sets.newIdentityHashSet();
+
+  public DesugaredLibraryRetargeter(AppView<?> appView) {
+    this.appView = appView;
+    if (appView.options().desugaredLibraryConfiguration.getRetargetCoreLibMember().isEmpty()) {
+      return;
+    }
+    new RetargetingSetup().setUpRetargeting();
+  }
+
+  public static void checkForAssumedLibraryTypes(AppView<?> appView) {
+    Map<DexString, Map<DexType, DexType>> retargetCoreLibMember =
+        appView.options().desugaredLibraryConfiguration.getRetargetCoreLibMember();
+    for (DexString methodName : retargetCoreLibMember.keySet()) {
+      for (DexType inType : retargetCoreLibMember.get(methodName).keySet()) {
+        DexClass typeClass = appView.definitionFor(inType);
+        if (typeClass == null) {
+          warnMissingRetargetCoreLibraryMember(inType, appView);
+        }
+      }
+    }
+  }
+
+  private static void warnMissingRetargetCoreLibraryMember(DexType type, AppView<?> appView) {
+    StringDiagnostic warning =
+        new StringDiagnostic(
+            "Cannot retarget core library member "
+                + type.getName()
+                + " because the class is missing.");
+    appView.options().reporter.warning(warning);
+  }
+
+  // Used by the ListOfBackportedMethods utility.
+  void visit(Consumer<DexMethod> consumer) {
+    retargetLibraryMember.keySet().forEach(consumer);
+  }
+
+  public void desugar(IRCode code) {
+    if (retargetLibraryMember.isEmpty()) {
+      return;
+    }
+
+    InstructionListIterator iterator = code.instructionListIterator();
+    while (iterator.hasNext()) {
+      Instruction instruction = iterator.next();
+      if (!instruction.isInvokeMethod()) {
+        continue;
+      }
+
+      InvokeMethod invoke = instruction.asInvokeMethod();
+      DexMethod retarget = getRetargetLibraryMember(invoke.getInvokedMethod());
+      if (retarget == null) {
+        if (!matchesNonFinalHolderRewrite(invoke.getInvokedMethod())) {
+          continue;
+        }
+        // We need to force resolution, even on d8, to know if the invoke has to be rewritten.
+        ResolutionResult resolutionResult =
+            appView
+                .appInfoForDesugaring()
+                .resolveMethod(invoke.getInvokedMethod(), invoke.getInterfaceBit());
+        if (resolutionResult.isFailedResolution()) {
+          continue;
+        }
+        DexEncodedMethod singleTarget = resolutionResult.getSingleTarget();
+        assert singleTarget != null;
+        retarget = getRetargetLibraryMember(singleTarget.method);
+        if (retarget == null) {
+          continue;
+        }
+      }
+
+      // Due to emulated dispatch, we have to rewrite invoke-super differently or we end up in
+      // infinite loops. We do direct resolution. This is a very uncommon case.
+      if (invoke.isInvokeSuper() && matchesNonFinalHolderRewrite(invoke.getInvokedMethod())) {
+        DexEncodedMethod dexEncodedMethod =
+            appView
+                .appInfoForDesugaring()
+                .lookupSuperTarget(invoke.getInvokedMethod(), code.context());
+        // Final methods can be rewritten as a normal invoke.
+        if (dexEncodedMethod != null && !dexEncodedMethod.isFinal()) {
+          DexMethod retargetMethod =
+              appView
+                  .options()
+                  .desugaredLibraryConfiguration
+                  .retargetMethod(dexEncodedMethod, appView);
+          if (retargetMethod != null) {
+            iterator.replaceCurrentInstruction(
+                new InvokeStatic(retargetMethod, invoke.outValue(), invoke.arguments()));
+          }
+          continue;
+        }
+      }
+
+      iterator.replaceCurrentInstruction(
+          new InvokeStatic(retarget, invoke.outValue(), invoke.inValues()));
+    }
+  }
+
+  private DexMethod getRetargetLibraryMember(DexMethod method) {
+    Map<DexType, DexType> backportCoreLibraryMembers =
+        appView.options().desugaredLibraryConfiguration.getBackportCoreLibraryMember();
+    if (backportCoreLibraryMembers.containsKey(method.holder)) {
+      DexType newHolder = backportCoreLibraryMembers.get(method.holder);
+      return appView.dexItemFactory().createMethod(newHolder, method.proto, method.name);
+    }
+    return retargetLibraryMember.get(method);
+  }
+
+  private boolean matchesNonFinalHolderRewrite(DexMethod method) {
+    List<DexMethod> dexMethods = nonFinalHolderRewrites.get(method.name);
+    if (dexMethods == null) {
+      return false;
+    }
+    for (DexMethod dexMethod : dexMethods) {
+      if (method.match(dexMethod)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  private class RetargetingSetup {
+
+    private void setUpRetargeting() {
+      Map<DexString, Map<DexType, DexType>> retargetCoreLibMember =
+          appView.options().desugaredLibraryConfiguration.getRetargetCoreLibMember();
+      for (DexString methodName : retargetCoreLibMember.keySet()) {
+        for (DexType inType : retargetCoreLibMember.get(methodName).keySet()) {
+          DexClass typeClass = appView.definitionFor(inType);
+          if (typeClass != null) {
+            DexType newHolder = retargetCoreLibMember.get(methodName).get(inType);
+            List<DexEncodedMethod> found = findDexEncodedMethodsWithName(methodName, typeClass);
+            for (DexEncodedMethod encodedMethod : found) {
+              if (!typeClass.isFinal()) {
+                nonFinalHolderRewrites.putIfAbsent(encodedMethod.method.name, new ArrayList<>());
+                nonFinalHolderRewrites.get(encodedMethod.method.name).add(encodedMethod.method);
+                if (!encodedMethod.isStatic()) {
+                  if (InterfaceMethodRewriter.isEmulatedInterfaceDispatch(appView, encodedMethod)) {
+                    // In this case interface method rewriter takes care of it.
+                    continue;
+                  } else if (!encodedMethod.isFinal()) {
+                    // Virtual rewrites require emulated dispatch for inheritance.
+                    // The call is rewritten to the dispatch holder class instead.
+                    handleEmulateDispatch(appView, encodedMethod);
+                    newHolder = dispatchHolderTypeFor(encodedMethod);
+                  }
+                }
+              }
+              DexProto proto = encodedMethod.method.proto;
+              DexMethod method = appView.dexItemFactory().createMethod(inType, proto, methodName);
+              retargetLibraryMember.put(
+                  method, computeRetargetMethod(method, encodedMethod.isStatic(), newHolder));
+            }
+          }
+        }
+      }
+    }
+
+    private DexMethod computeRetargetMethod(DexMethod method, boolean isStatic, DexType newHolder) {
+      DexItemFactory factory = appView.dexItemFactory();
+      DexProto newProto = isStatic ? method.proto : factory.prependHolderToProto(method);
+      return factory.createMethod(newHolder, newProto, method.name);
+    }
+
+    private List<DexEncodedMethod> findDexEncodedMethodsWithName(
+        DexString methodName, DexClass clazz) {
+      List<DexEncodedMethod> found = new ArrayList<>();
+      for (DexEncodedMethod encodedMethod : clazz.methods()) {
+        if (encodedMethod.method.name == methodName) {
+          found.add(encodedMethod);
+        }
+      }
+      assert found.size() > 0 : "Should have found a method (library specifications).";
+      return found;
+    }
+
+    private void handleEmulateDispatch(AppView<?> appView, DexEncodedMethod method) {
+      emulatedDispatchMethods.add(method);
+      if (!appView.options().isDesugaredLibraryCompilation()) {
+        // Add rewrite rules so keeps rules are correctly generated in the program.
+        DexType dispatchInterfaceType = dispatchInterfaceTypeFor(method);
+        appView.rewritePrefix.rewriteType(dispatchInterfaceType, dispatchInterfaceType);
+        DexType dispatchHolderType = dispatchHolderTypeFor(method);
+        appView.rewritePrefix.rewriteType(dispatchHolderType, dispatchHolderType);
+      }
+    }
+  }
+
+  public void synthesizeRetargetClasses(
+      DexApplication.Builder<?> builder, ExecutorService executorService, IRConverter converter)
+      throws ExecutionException {
+    new EmulatedDispatchTreeFixer().fixApp(builder, executorService, converter);
+  }
+
+  // The rewrite of virtual calls requires to go through emulate dispatch. This class is responsible
+  // for inserting interfaces on library boundaries and forwarding methods in the program, and to
+  // synthesize the interfaces and emulated dispatch classes in the desugared library.
+  class EmulatedDispatchTreeFixer {
+
+    void fixApp(
+        DexApplication.Builder<?> builder, ExecutorService executorService, IRConverter converter)
+        throws ExecutionException {
+      if (appView.options().isDesugaredLibraryCompilation()) {
+        synthesizeEmulatedDispatchMethods(builder);
+      } else {
+        addInterfacesAndForwardingMethods(executorService, converter);
+      }
+    }
+
+    private void addInterfacesAndForwardingMethods(
+        ExecutorService executorService, IRConverter converter) throws ExecutionException {
+      assert !appView.options().isDesugaredLibraryCompilation();
+      Map<DexType, List<DexEncodedMethod>> map = Maps.newIdentityHashMap();
+      for (DexEncodedMethod emulatedDispatchMethod : emulatedDispatchMethods) {
+        map.putIfAbsent(emulatedDispatchMethod.getHolderType(), new ArrayList<>(1));
+        map.get(emulatedDispatchMethod.getHolderType()).add(emulatedDispatchMethod);
+      }
+      SortedProgramMethodSet addedMethods = SortedProgramMethodSet.create();
+      for (DexProgramClass clazz : appView.appInfo().classes()) {
+        if (clazz.superType == null) {
+          assert clazz.type == appView.dexItemFactory().objectType : clazz.type.toSourceString();
+          continue;
+        }
+        DexClass superclass = appView.definitionFor(clazz.superType);
+        // Only performs computation if superclass is a library class, but not object to filter out
+        // the most common case.
+        if (superclass != null
+            && superclass.isLibraryClass()
+            && superclass.type != appView.dexItemFactory().objectType) {
+          map.forEach(
+              (type, methods) -> {
+                if (inherit(superclass.asLibraryClass(), type, emulatedDispatchMethods)) {
+                  addInterfacesAndForwardingMethods(
+                      clazz, methods, method -> addedMethods.createAndAdd(clazz, method));
+                }
+              });
+        }
+      }
+      converter.processMethodsConcurrently(addedMethods, executorService);
+    }
+
+    private boolean inherit(
+        DexLibraryClass clazz, DexType typeToInherit, Set<DexEncodedMethod> retarget) {
+      DexLibraryClass current = clazz;
+      while (current.type != appView.dexItemFactory().objectType) {
+        if (current.type == typeToInherit) {
+          return true;
+        }
+        DexClass dexClass = appView.definitionFor(current.superType);
+        if (dexClass == null || dexClass.isClasspathClass()) {
+          reportInvalidLibrarySupertype(current, retarget);
+          return false;
+        } else if (dexClass.isProgramClass()) {
+          // If dexClass is a program class, then it is already correctly desugared.
+          return false;
+        }
+        current = dexClass.asLibraryClass();
+      }
+      return false;
+    }
+
+    private void addInterfacesAndForwardingMethods(
+        DexProgramClass clazz,
+        List<DexEncodedMethod> methods,
+        Consumer<DexEncodedMethod> newForwardingMethodsConsumer) {
+      // DesugaredLibraryRetargeter emulate dispatch: insertion of a marker interface & forwarding
+      // methods.
+      // We cannot use the ClassProcessor since this applies up to 26, while the ClassProcessor
+      // applies up to 24.
+      for (DexEncodedMethod method : methods) {
+        clazz.addExtraInterfaces(
+            Collections.singletonList(dispatchInterfaceTypeFor(method)), appView.dexItemFactory());
+        if (clazz.lookupVirtualMethod(method.getReference()) == null) {
+          DexEncodedMethod newMethod = createForwardingMethod(method, clazz);
+          clazz.addVirtualMethod(newMethod);
+          newForwardingMethodsConsumer.accept(newMethod);
+        }
+      }
+    }
+
+    private DexEncodedMethod createForwardingMethod(DexEncodedMethod target, DexClass clazz) {
+      // 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 =
+          appView.options().desugaredLibraryConfiguration.retargetMethod(target, appView);
+      assert forwardMethod != null && forwardMethod != target.getReference();
+      return DexEncodedMethod.createDesugaringForwardingMethod(
+          target, clazz, forwardMethod, appView.dexItemFactory());
+    }
+
+    private void synthesizeEmulatedDispatchMethods(DexApplication.Builder<?> builder) {
+      assert appView.options().isDesugaredLibraryCompilation();
+      if (emulatedDispatchMethods.isEmpty()) {
+        return;
+      }
+      ClassAccessFlags itfAccessFlags =
+          ClassAccessFlags.fromSharedAccessFlags(
+              Constants.ACC_PUBLIC
+                  | Constants.ACC_SYNTHETIC
+                  | Constants.ACC_ABSTRACT
+                  | Constants.ACC_INTERFACE);
+      ClassAccessFlags holderAccessFlags =
+          ClassAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC);
+      for (DexEncodedMethod emulatedDispatchMethod : emulatedDispatchMethods) {
+        // Dispatch interface.
+        DexType interfaceType = dispatchInterfaceTypeFor(emulatedDispatchMethod);
+        DexEncodedMethod itfMethod =
+            generateInterfaceDispatchMethod(emulatedDispatchMethod, interfaceType);
+        BackportedMethodRewriter.synthesizeClassWithUniqueMethod(
+            builder,
+            itfAccessFlags,
+            interfaceType,
+            itfMethod,
+            "desugared library dispatch interface",
+            false,
+            appView);
+        // Dispatch holder.
+        DexType holderType = dispatchHolderTypeFor(emulatedDispatchMethod);
+        DexEncodedMethod dispatchMethod =
+            generateHolderDispatchMethod(emulatedDispatchMethod, holderType, itfMethod.method);
+        BackportedMethodRewriter.synthesizeClassWithUniqueMethod(
+            builder,
+            holderAccessFlags,
+            holderType,
+            dispatchMethod,
+            "desugared library dispatch class",
+            false,
+            appView);
+      }
+    }
+
+    private DexEncodedMethod generateInterfaceDispatchMethod(
+        DexEncodedMethod emulatedDispatchMethod, DexType interfaceType) {
+      MethodAccessFlags flags =
+          MethodAccessFlags.fromSharedAccessFlags(
+              Constants.ACC_PUBLIC | Constants.ACC_ABSTRACT | Constants.ACC_SYNTHETIC, false);
+      DexMethod newMethod =
+          appView
+              .dexItemFactory()
+              .createMethod(
+                  interfaceType,
+                  emulatedDispatchMethod.getProto(),
+                  emulatedDispatchMethod.getName());
+      return new DexEncodedMethod(
+          newMethod, flags, DexAnnotationSet.empty(), ParameterAnnotationsList.empty(), null, true);
+    }
+
+    private DexEncodedMethod generateHolderDispatchMethod(
+        DexEncodedMethod emulatedDispatchMethod, DexType dispatchHolder, DexMethod itfMethod) {
+      // The method should look like:
+      // static foo(rcvr, arg0, arg1) {
+      //    if (rcvr instanceof interfaceType) {
+      //      return invoke-interface receiver.foo(arg0, arg1);
+      //    } else {
+      //      return DesugarX.foo(rcvr, arg0, arg1)
+      //    }
+      // We do not deal with complex cases (multiple retargeting of the same signature in the
+      // same inheritance tree, etc., since they do not happen in the most common desugared library.
+      DexMethod desugarMethod =
+          appView
+              .options()
+              .desugaredLibraryConfiguration
+              .retargetMethod(emulatedDispatchMethod, appView);
+      assert desugarMethod != null; // This method is reached only for retarget core lib members.
+      DexMethod newMethod =
+          appView
+              .dexItemFactory()
+              .createMethod(dispatchHolder, desugarMethod.proto, emulatedDispatchMethod.getName());
+      return DexEncodedMethod.toEmulateDispatchLibraryMethod(
+          emulatedDispatchMethod.getHolderType(),
+          newMethod,
+          desugarMethod,
+          itfMethod,
+          Collections.emptyList(),
+          appView);
+    }
+  }
+
+  private void reportInvalidLibrarySupertype(
+      DexLibraryClass libraryClass, Set<DexEncodedMethod> retarget) {
+    DexClass dexClass = appView.definitionFor(libraryClass.superType);
+    String message;
+    if (dexClass == null) {
+      message = "missing";
+    } else if (dexClass.isClasspathClass()) {
+      message = "a classpath class";
+    } else {
+      message = "INVALID";
+      assert false;
+    }
+    appView
+        .options()
+        .warningInvalidLibrarySuperclassForDesugar(
+            dexClass == null ? libraryClass.getOrigin() : dexClass.getOrigin(),
+            libraryClass.type,
+            libraryClass.superType,
+            message,
+            retarget);
+  }
+
+  private DexType dispatchInterfaceTypeFor(DexEncodedMethod method) {
+    return dispatchTypeFor(method, "dispatchInterface");
+  }
+
+  private DexType dispatchHolderTypeFor(DexEncodedMethod method) {
+    return dispatchTypeFor(method, "dispatchHolder");
+  }
+
+  private DexType dispatchTypeFor(DexEncodedMethod method, String suffix) {
+    String descriptor =
+        "L"
+            + appView
+                .options()
+                .desugaredLibraryConfiguration
+                .getSynthesizedLibraryClassesPackagePrefix()
+            + DESUGAR_LIB_RETARGET_CLASS_NAME_PREFIX
+            + '$'
+            + method.getHolderType().getName()
+            + '$'
+            + method.getName()
+            + '$'
+            + suffix
+            + ';';
+    return appView.dexItemFactory().createSynthesizedType(descriptor);
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
index 14f9443..ea75f98 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -868,7 +868,7 @@
   private void duplicateEmulatedInterfaces() {
     // All classes implementing an emulated interface now implements the interface and the
     // emulated one, as well as hidden overrides, for correct emulated dispatch.
-    for (DexClass clazz : appView.appInfo().classes()) {
+    for (DexProgramClass clazz : appView.appInfo().classes()) {
       if (clazz.type == appView.dexItemFactory().objectType) {
         continue;
       }
@@ -888,17 +888,11 @@
           }
         }
         // Remove duplicates.
-        extraInterfaces = new ArrayList<>(new LinkedHashSet<>(extraInterfaces));
-      }
-      if (!extraInterfaces.isEmpty()) {
-        DexType[] newInterfaces =
-            Arrays.copyOf(
-                clazz.interfaces.values, clazz.interfaces.size() + extraInterfaces.size());
-        for (int i = clazz.interfaces.size(); i < newInterfaces.length; i++) {
-          newInterfaces[i] = extraInterfaces.get(i - clazz.interfaces.size());
+        if (extraInterfaces.size() > 1) {
+          extraInterfaces = new ArrayList<>(new LinkedHashSet<>(extraInterfaces));
         }
-        clazz.interfaces = new DexTypeList(newInterfaces);
       }
+      clazz.addExtraInterfaces(extraInterfaces, appView.dexItemFactory());
     }
   }
 
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LibrarySubclassInterfaceTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LibrarySubclassInterfaceTest.java
index 6e300ba..4b9f409 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LibrarySubclassInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LibrarySubclassInterfaceTest.java
@@ -25,6 +25,10 @@
 import java.util.concurrent.ConcurrentMap;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+<<<<<<< HEAD
+=======
+import org.junit.Assume;
+>>>>>>> 6a837db0b... Desugared lib: Fix getGenericTypes
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;