Don't issue warnings for missing interfaces for virtual invokes.

Fixes: 199815247
Change-Id: I18ad3773465a4041ea75163b2312c6c941ee57fa
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
index c4c281d..9ee3f54 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
@@ -315,9 +315,11 @@
     // If the target holder does not resolve we may want to issue diagnostics.
     DexClass holder = appView.definitionForHolder(invoke.getMethod(), context);
     if (holder == null) {
-      // NOTE: leave unchanged those calls to undefined targets. This may lead to runtime
-      // exception but we can not report it as error since it can also be the intended
-      // behavior.
+      if (invoke.isInvokeVirtual() || invoke.isInvokeInterface()) {
+        // For virtual targets we should not report anything as any virtual dispatch just remains.
+        return DesugarDescription.nothing();
+      }
+      // For static, private and special invokes, they may require desugaring and should warn.
       return DesugarDescription.builder()
           .addScanEffect(
               () -> {
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/MissingInterfaceVirtualTargetsTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/MissingInterfaceVirtualTargetsTest.java
new file mode 100644
index 0000000..afb96e2
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/MissingInterfaceVirtualTargetsTest.java
@@ -0,0 +1,77 @@
+// 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.resolution.interfacetargets;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.StringUtils;
+import java.nio.file.Path;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class MissingInterfaceVirtualTargetsTest extends TestBase {
+
+  static final String EXPECTED = StringUtils.lines("I.foo", "I.foo");
+
+  private final TestParameters parameters;
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters()
+        .withAllRuntimes()
+        .withApiLevel(AndroidApiLevel.B)
+        .enableApiLevelsForCf()
+        .build();
+  }
+
+  public MissingInterfaceVirtualTargetsTest(TestParameters parameters) {
+    this.parameters = parameters;
+  }
+
+  @Test
+  public void test() throws Exception {
+    Path out =
+        testForD8(parameters.getBackend())
+            .addProgramClasses(TestClass.class)
+            .setMinApi(parameters.getApiLevel())
+            .compile()
+            .assertNoMessages()
+            .writeToZip();
+    testForD8(parameters.getBackend())
+        .addProgramClasses(I.class, A.class)
+        .setMinApi(parameters.getApiLevel())
+        .addRunClasspathFiles(out)
+        .run(parameters.getRuntime(), TestClass.class)
+        .assertSuccessWithOutput(EXPECTED);
+  }
+
+  interface I {
+    default void foo() {
+      System.out.println("I.foo");
+    }
+  }
+
+  static class A implements I {
+    // No override.
+  }
+
+  static class TestClass {
+
+    static void targetI(I i) {
+      // This invoke-interface target should not cause missing class warnings.
+      i.foo();
+    }
+
+    public static void main(String[] args) {
+      A a = new A();
+      targetI(a);
+      // This invoke-virtual target should not cause missing class warnings.
+      a.foo();
+    }
+  }
+}