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) {