Desugared lib API conversion foreach

- R8 was not able to compile guava with
  desugared lib on due to API conversion,
  it is now possible

Bug: 142507849
Change-Id: Ibabd3f3e6ec16c03e2f248040b6612d15e8fb647
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java
index 708cabb8..d60ac1f 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java
@@ -172,6 +172,16 @@
   private synchronized void generateCallBack(DexClass dexClass, DexEncodedMethod originalMethod) {
     DexMethod methodToInstall =
         methodWithVivifiedTypeInSignature(originalMethod.method, dexClass.type, appView);
+    if (dexClass.isInterface()
+        && originalMethod.isDefaultMethod()
+        && !appView.options().canUseDefaultAndStaticInterfaceMethods()) {
+      // Interface method desugaring has been performed before and all the call-backs will be
+      // generated in all implementors of the interface. R8 cannot introduce new
+      // default methods at this point, but R8 does not need to do anything (the interface
+      // already implements the vivified version through inheritance, and all implementors
+      // support the call-back correctly).
+      return;
+    }
     CfCode cfCode =
         new APIConverterWrapperCfCodeProvider(
             appView, originalMethod.method, null, this, dexClass.isInterface())
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/conversionTests/ConversionIntroduceInterfaceMethodTest.java b/src/test/java/com/android/tools/r8/desugar/corelib/conversionTests/ConversionIntroduceInterfaceMethodTest.java
new file mode 100644
index 0000000..f38aa3b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/conversionTests/ConversionIntroduceInterfaceMethodTest.java
@@ -0,0 +1,153 @@
+// 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.desugar.corelib.conversionTests;
+
+import com.android.tools.r8.TestRuntime.DexRuntime;
+import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.StringUtils;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.function.Consumer;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Test;
+
+public class ConversionIntroduceInterfaceMethodTest extends APIConversionTestBase {
+
+  @Test
+  public void testNoInterfaceMethods() throws Exception {
+    Path customLib = testForD8().addProgramClasses(CustomLibClass.class).compile().writeToZip();
+    testForD8()
+        .setMinApi(AndroidApiLevel.B)
+        .addProgramClasses(
+            MyCollectionInterface.class,
+            MyCollectionInterfaceAbstract.class,
+            MyCollection.class,
+            Executor.class)
+        .addLibraryClasses(CustomLibClass.class)
+        .enableCoreLibraryDesugaring(AndroidApiLevel.B)
+        .compile()
+        .addDesugaredCoreLibraryRunClassPath(
+            this::buildDesugaredLibraryWithConversionExtension, AndroidApiLevel.B)
+        .addRunClasspathFiles(customLib)
+        .run(new DexRuntime(DexVm.ART_9_0_0_HOST), Executor.class)
+        .assertSuccessWithOutput(
+            StringUtils.lines(
+                "action called from j$ consumer",
+                "forEach called",
+                "action called from java consumer",
+                "forEach called"));
+  }
+
+  static class CustomLibClass {
+
+    @SuppressWarnings({"unchecked", "WeakerAccess"})
+    public static void callForeach(Iterable iterable) {
+      iterable.forEach(x -> System.out.println("action called from java consumer"));
+    }
+  }
+
+  static class Executor {
+
+    @SuppressWarnings("RedundantOperationOnEmptyContainer")
+    public static void main(String[] args) {
+      MyCollection<String> strings = new MyCollection<>();
+      // Call foreach with j$ consumer.
+      strings.forEach(x -> System.out.println("action called from j$ consumer"));
+      // Call foreach with java consumer.
+      CustomLibClass.callForeach(strings);
+    }
+  }
+
+  interface MyCollectionInterface<E> extends Collection<E> {
+
+    // The following method override a method from Iterable and use a desugared type.
+    // API conversion is required.
+    @Override
+    default void forEach(Consumer<? super E> action) {
+      action.accept(null);
+      System.out.println("forEach called");
+    }
+  }
+
+  @SuppressWarnings("ConstantConditions")
+  static class MyCollection<E> implements MyCollectionInterface<E> {
+
+    @Override
+    public int size() {
+      return 0;
+    }
+
+    @Override
+    public boolean isEmpty() {
+      return false;
+    }
+
+    @Override
+    public boolean contains(Object o) {
+      return false;
+    }
+
+    @NotNull
+    @Override
+    public Iterator<E> iterator() {
+      return null;
+    }
+
+    @NotNull
+    @Override
+    public Object[] toArray() {
+      return new Object[0];
+    }
+
+    @NotNull
+    @Override
+    public <T> T[] toArray(@NotNull T[] a) {
+      return null;
+    }
+
+    @Override
+    public boolean add(E e) {
+      return false;
+    }
+
+    @Override
+    public boolean remove(Object o) {
+      return false;
+    }
+
+    @Override
+    public boolean containsAll(@NotNull Collection<?> c) {
+      return false;
+    }
+
+    @Override
+    public boolean addAll(@NotNull Collection<? extends E> c) {
+      return false;
+    }
+
+    @Override
+    public boolean removeAll(@NotNull Collection<?> c) {
+      return false;
+    }
+
+    @Override
+    public boolean retainAll(@NotNull Collection<?> c) {
+      return false;
+    }
+
+    @Override
+    public void clear() {}
+  }
+
+  interface MyCollectionInterfaceAbstract<E> extends Collection<E> {
+
+    // The following method override a method from Iterable and use a desugared type.
+    // API conversion is required.
+    @Override
+    void forEach(Consumer<? super E> action);
+  }
+}