Don't report missing interfaces in R8 interface desugaring.

Bug: 175659048
Bug: 179341237
Fixes: 198368663
Change-Id: I45f38390c064d642a95125a33d85aa5b6febd280
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringEventConsumer.java b/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringEventConsumer.java
index e4a34c4..8f5178e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringEventConsumer.java
@@ -6,14 +6,17 @@
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexClasspathClass;
 import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.conversion.D8MethodProcessor;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibraryRetargeterSynthesizerEventConsumer.DesugaredLibraryRetargeterPostProcessingEventConsumer;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibraryWrapperSynthesizerEventConsumer.DesugaredLibraryAPICallbackSynthesizorEventConsumer;
+import com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper;
 import com.android.tools.r8.ir.desugar.itf.InterfaceProcessingDesugaringEventConsumer;
 import com.android.tools.r8.shaking.Enqueuer.SyntheticAdditions;
 import com.android.tools.r8.utils.collections.ProgramMethodSet;
 import java.util.concurrent.ExecutionException;
+import java.util.function.BiConsumer;
 
 /**
  * Specialized Event consumer for desugaring finalization. During finalization, it is not possible
@@ -31,8 +34,10 @@
   }
 
   public static R8PostProcessingDesugaringEventConsumer createForR8(
-      SyntheticAdditions additions, CfInstructionDesugaringCollection desugaring) {
-    return new R8PostProcessingDesugaringEventConsumer(additions, desugaring);
+      SyntheticAdditions additions,
+      CfInstructionDesugaringCollection desugaring,
+      BiConsumer<DexProgramClass, DexType> missingClassConsumer) {
+    return new R8PostProcessingDesugaringEventConsumer(additions, desugaring, missingClassConsumer);
   }
 
   public abstract void finalizeDesugaring() throws ExecutionException;
@@ -60,6 +65,12 @@
     }
 
     @Override
+    public void warnMissingInterface(
+        DexProgramClass context, DexType missing, InterfaceDesugaringSyntheticHelper helper) {
+      helper.warnMissingInterface(context, context, missing);
+    }
+
+    @Override
     public void acceptDesugaredLibraryRetargeterDispatchClasspathClass(DexClasspathClass clazz) {
       // Intentionally empty.
     }
@@ -114,11 +125,21 @@
 
     private final SyntheticAdditions additions;
     private final CfInstructionDesugaringCollection desugaring;
+    private final BiConsumer<DexProgramClass, DexType> missingClassConsumer;
 
     R8PostProcessingDesugaringEventConsumer(
-        SyntheticAdditions additions, CfInstructionDesugaringCollection desugaring) {
+        SyntheticAdditions additions,
+        CfInstructionDesugaringCollection desugaring,
+        BiConsumer<DexProgramClass, DexType> missingClassConsumer) {
       this.additions = additions;
       this.desugaring = desugaring;
+      this.missingClassConsumer = missingClassConsumer;
+    }
+
+    @Override
+    public void warnMissingInterface(
+        DexProgramClass context, DexType missing, InterfaceDesugaringSyntheticHelper helper) {
+      missingClassConsumer.accept(context, missing);
     }
 
     @Override
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
index 8661587..97d890c 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
@@ -51,6 +51,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BiConsumer;
 import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.function.Predicate;
@@ -295,10 +296,15 @@
 
     final DexClass directSubClass;
     final DexProgramClass closestProgramSubClass;
+    final BiConsumer<DexProgramClass, DexType> reportMissingTypeCallback;
 
-    public ReportingContext(DexClass directSubClass, DexProgramClass closestProgramSubClass) {
+    public ReportingContext(
+        DexClass directSubClass,
+        DexProgramClass closestProgramSubClass,
+        BiConsumer<DexProgramClass, DexType> reportMissingTypeCallback) {
       this.directSubClass = directSubClass;
       this.closestProgramSubClass = closestProgramSubClass;
+      this.reportMissingTypeCallback = reportMissingTypeCallback;
     }
 
     ReportingContext forClass(DexClass directSubClass) {
@@ -306,15 +312,16 @@
           directSubClass,
           directSubClass.isProgramClass()
               ? directSubClass.asProgramClass()
-              : closestProgramSubClass);
+              : closestProgramSubClass,
+          reportMissingTypeCallback);
     }
 
     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);
+    public void reportMissingType(DexType missingType) {
+      reportMissingTypeCallback.accept(closestProgramSubClass, missingType);
     }
   }
 
@@ -324,7 +331,7 @@
     static final LibraryReportingContext LIBRARY_CONTEXT = new LibraryReportingContext();
 
     LibraryReportingContext() {
-      super(null, null);
+      super(null, null, null);
     }
 
     @Override
@@ -338,7 +345,7 @@
     }
 
     @Override
-    public void reportMissingType(DexType missingType, InterfaceDesugaringSyntheticHelper helper) {
+    public void reportMissingType(DexType missingType) {
       // Ignore missing types in the library.
     }
   }
@@ -400,7 +407,12 @@
   public void process(
       DexProgramClass clazz, InterfaceProcessingDesugaringEventConsumer eventConsumer) {
     if (!clazz.isInterface()) {
-      visitClassInfo(clazz, new ReportingContext(clazz, clazz));
+      visitClassInfo(
+          clazz,
+          new ReportingContext(
+              clazz,
+              clazz,
+              (context, missing) -> eventConsumer.warnMissingInterface(context, missing, helper)));
     }
   }
 
@@ -864,7 +876,7 @@
     }
     DexClass clazz = context.definitionFor(type, appView);
     if (clazz == null) {
-      context.reportMissingType(type, helper);
+      context.reportMissingType(type);
       return null;
     }
     return clazz;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
index 9ee3606..5576f78 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
@@ -526,7 +526,8 @@
     return shouldIgnoreFromReportsPredicate.test(missing);
   }
 
-  void warnMissingInterface(DexClass classToDesugar, DexClass implementing, DexType missing) {
+  public void warnMissingInterface(
+      DexClass classToDesugar, DexClass implementing, DexType missing) {
     // We use contains() on non hashed collection, but we know it's a 8 cases collection.
     // j$ interfaces won't be missing, they are in the desugared library.
     if (shouldIgnoreFromReports(missing)) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessingDesugaringEventConsumer.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessingDesugaringEventConsumer.java
index e16f254..49d843d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessingDesugaringEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessingDesugaringEventConsumer.java
@@ -6,6 +6,7 @@
 
 import com.android.tools.r8.graph.DexClasspathClass;
 import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.ProgramMethod;
 
 // TODO(b/183998768): Consider forcing the processing of interface methods in D8 akin to R8.
@@ -18,4 +19,7 @@
 
   void acceptEmulatedInterfaceMarkerInterface(
       DexProgramClass clazz, DexClasspathClass newInterface);
+
+  void warnMissingInterface(
+      DexProgramClass context, DexType missing, InterfaceDesugaringSyntheticHelper helper);
 }
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 66e9136..895e610 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -20,6 +20,7 @@
 import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
 import com.android.tools.r8.contexts.CompilationContext.ProcessorContext;
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.errors.InterfaceDesugarMissingTypeDiagnostic;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
 import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
@@ -108,6 +109,7 @@
 import com.android.tools.r8.logging.Log;
 import com.android.tools.r8.naming.identifiernamestring.IdentifierNameStringLookupResult;
 import com.android.tools.r8.naming.identifiernamestring.IdentifierNameStringTypeLookupResult;
+import com.android.tools.r8.position.Position;
 import com.android.tools.r8.shaking.AnnotationMatchResult.MatchedAnnotation;
 import com.android.tools.r8.shaking.DelayedRootSetActionItem.InterfaceMethodSyntheticBridgeAction;
 import com.android.tools.r8.shaking.EnqueuerEvent.ClassEnqueuerEvent;
@@ -3933,7 +3935,19 @@
     assert workList.isEmpty();
 
     R8PostProcessingDesugaringEventConsumer eventConsumer =
-        CfPostProcessingDesugaringEventConsumer.createForR8(syntheticAdditions, desugaring);
+        CfPostProcessingDesugaringEventConsumer.createForR8(
+            syntheticAdditions,
+            desugaring,
+            (context, missing) ->
+                missingClassesBuilder.addNewMissingClassWithDesugarDiagnostic(
+                    missing,
+                    context,
+                    new InterfaceDesugarMissingTypeDiagnostic(
+                        context.getOrigin(),
+                        Position.UNKNOWN,
+                        missing.asClassReference(),
+                        context.getType().asClassReference(),
+                        null)));
     InterfaceMethodProcessorFacade interfaceDesugaring =
         desugaring.getInterfaceMethodPostProcessingDesugaringR8(
             ExcludeDexResources, liveMethods::contains, interfaceProcessor);
diff --git a/src/main/java/com/android/tools/r8/shaking/MissingClasses.java b/src/main/java/com/android/tools/r8/shaking/MissingClasses.java
index 1dd5360..ac8f1fb 100644
--- a/src/main/java/com/android/tools/r8/shaking/MissingClasses.java
+++ b/src/main/java/com/android/tools/r8/shaking/MissingClasses.java
@@ -11,6 +11,7 @@
 import com.android.tools.r8.diagnostic.internal.DefinitionContextUtils;
 import com.android.tools.r8.diagnostic.internal.MissingClassInfoImpl;
 import com.android.tools.r8.diagnostic.internal.MissingDefinitionsDiagnosticImpl;
+import com.android.tools.r8.errors.DesugarDiagnostic;
 import com.android.tools.r8.errors.dontwarn.DontWarnConfiguration;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -89,6 +90,17 @@
       }
     }
 
+    public void addNewMissingClassWithDesugarDiagnostic(
+        DexType type, ProgramDerivedContext context, DesugarDiagnostic diagnostic) {
+      // TODO(b/175659048): At this point we just throw out the diagnostic and report the
+      //  missing classes only. We should instead report the most specific diagnostic as the
+      //  information about missing for desugar is strictly more valuable than just missing.
+      //  Note that we should have deterministic reporting and so we should collect all of the
+      //  contexts for which desugaring needed the type and report all of those in the same
+      //  way as we do for missing classes.
+      addNewMissingClass(type, context);
+    }
+
     public void legacyAddNewMissingClass(DexType type) {
       if (!alreadyMissingClasses.contains(type)) {
         // The legacy reporting is context insensitive, so we just use an empty set of contexts.
diff --git a/src/test/java/com/android/tools/r8/CompileWithJdkClassFileProviderTest.java b/src/test/java/com/android/tools/r8/CompileWithJdkClassFileProviderTest.java
index 0637a0b..2a8f1bb 100644
--- a/src/test/java/com/android/tools/r8/CompileWithJdkClassFileProviderTest.java
+++ b/src/test/java/com/android/tools/r8/CompileWithJdkClassFileProviderTest.java
@@ -1,6 +1,7 @@
 package com.android.tools.r8;
 
 import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
+import static com.android.tools.r8.DiagnosticsMatcher.diagnosticType;
 import static org.hamcrest.CoreMatchers.anyOf;
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.fail;
@@ -8,6 +9,7 @@
 
 import com.android.tools.r8.TestRuntime.CfRuntime;
 import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.diagnostic.MissingDefinitionsDiagnostic;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import java.util.List;
 import org.junit.Test;
@@ -92,15 +94,10 @@
             diagnostics -> {
               diagnostics.assertErrorsMatch(
                   diagnosticMessage(containsString("java.util.concurrent.Flow$Subscriber")));
-              if (parameters.isCfRuntime()) {
-                diagnostics.assertOnlyErrors();
-              } else {
-                // TODO(b/198368663): R8 will double report missing classes in itf desugaring.
-                diagnostics.assertWarningsMatch(
-                    diagnosticMessage(containsString("java.util.concurrent.Flow$Subscriber")));
-                diagnostics.assertErrorsCount(1);
-                diagnostics.assertWarningsCount(1);
-                diagnostics.assertInfosCount(0);
+              diagnostics.assertOnlyErrors();
+              if (parameters.isDexRuntime()) {
+                // TODO(b/175659048): This should likely be a desugar diagnostic.
+                diagnostics.assertErrorsMatch(diagnosticType(MissingDefinitionsDiagnostic.class));
               }
             });
       } catch (CompilationFailedException e) {