Emulated interface desugaring above 24
Change-Id: Ia175c867262dde1ab5d4e51605ab8b4a2df684a1
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs.json b/src/library_desugar/jdk11/desugar_jdk_libs.json
index 8cb9509..97c9ae5 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs.json
@@ -1,5 +1,5 @@
{
- "identifier": "com.tools.android:desugar_jdk_libs_configuration:2.0.1",
+ "identifier": "com.tools.android:desugar_jdk_libs_configuration:2.0.2",
"configuration_format_version": 100,
"required_compilation_api_level": 30,
"synthesized_library_classes_package_prefix": "j$.",
@@ -46,6 +46,20 @@
]
},
{
+ "api_level_below_or_equal": 33,
+ "api_level_greater_or_equal": 24,
+ "emulate_interface": {
+ "java.util.Collection": "j$.util.Collection"
+ },
+ "dont_rewrite": [
+ "boolean java.util.Collection#removeIf(java.util.function.Predicate)",
+ "java.util.Spliterator java.util.Collection#spliterator()",
+ "java.util.stream.Stream java.util.Collection#parallelStream()",
+ "java.util.stream.Stream java.util.Collection#stream()",
+ "void java.util.Collection#forEach(java.util.function.Consumer)"
+ ]
+ },
+ {
"api_level_below_or_equal": 23,
"rewrite_prefix": {
"java.io.DesugarBufferedReader": "j$.io.DesugarBufferedReader",
@@ -147,6 +161,12 @@
],
"program_flags": [
{
+ "api_level_below_or_equal": 33,
+ "amend_library_method": [
+ "public java.lang.Object[] java.util.Collection#toArray(java.util.function.IntFunction)"
+ ]
+ },
+ {
"api_level_below_or_equal": 32,
"api_level_greater_or_equal": 26,
"covariant_retarget_method": {
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_minimal.json b/src/library_desugar/jdk11/desugar_jdk_libs_minimal.json
index 119b674..15939bc 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_minimal.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_minimal.json
@@ -1,5 +1,5 @@
{
- "identifier": "com.tools.android:desugar_jdk_libs_configuration_minimal:2.0.1",
+ "identifier": "com.tools.android:desugar_jdk_libs_configuration_minimal:2.0.2",
"configuration_format_version": 100,
"required_compilation_api_level": 24,
"synthesized_library_classes_package_prefix": "j$.",
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_nio.json b/src/library_desugar/jdk11/desugar_jdk_libs_nio.json
index 0b7d6cf..c308b06 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_nio.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_nio.json
@@ -1,5 +1,5 @@
{
- "identifier": "com.tools.android:desugar_jdk_libs_configuration_nio:2.0.1",
+ "identifier": "com.tools.android:desugar_jdk_libs_configuration_nio:2.0.2",
"configuration_format_version": 100,
"required_compilation_api_level": 30,
"synthesized_library_classes_package_prefix": "j$.",
@@ -60,6 +60,20 @@
]
},
{
+ "api_level_below_or_equal": 33,
+ "api_level_greater_or_equal": 24,
+ "emulate_interface": {
+ "java.util.Collection": "j$.util.Collection"
+ },
+ "dont_rewrite": [
+ "boolean java.util.Collection#removeIf(java.util.function.Predicate)",
+ "java.util.Spliterator java.util.Collection#spliterator()",
+ "java.util.stream.Stream java.util.Collection#parallelStream()",
+ "java.util.stream.Stream java.util.Collection#stream()",
+ "void java.util.Collection#forEach(java.util.function.Consumer)"
+ ]
+ },
+ {
"api_level_below_or_equal": 25,
"rewrite_prefix": {
"java.io.DesugarFile": "j$.io.DesugarFile",
@@ -306,6 +320,12 @@
],
"program_flags": [
{
+ "api_level_below_or_equal": 33,
+ "amend_library_method": [
+ "public java.lang.Object[] java.util.Collection#toArray(java.util.function.IntFunction)"
+ ]
+ },
+ {
"api_level_below_or_equal": 32,
"api_level_greater_or_equal": 26,
"covariant_retarget_method": {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index ab044e3..751b635 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -359,10 +359,7 @@
workaroundAbstractMethodOnNonAbstractClassVerificationBug(executor);
DexApplication application = appView.appInfo().app();
D8MethodProcessor methodProcessor = new D8MethodProcessor(this, executor);
- InterfaceProcessor interfaceProcessor =
- appView.options().isInterfaceMethodDesugaringEnabled()
- ? new InterfaceProcessor(appView)
- : null;
+ InterfaceProcessor interfaceProcessor = InterfaceProcessor.create(appView);
timing.begin("IR conversion");
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
index aa8ca78..7905c6c 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
@@ -93,17 +93,15 @@
if (appView.options().enableTryWithResourcesDesugaring()) {
desugarings.add(new TwrInstructionDesugaring(appView));
}
- if (appView.options().isInterfaceMethodDesugaringEnabled()) {
- interfaceMethodRewriter =
- new InterfaceMethodRewriter(
- appView,
- SetUtils.newImmutableSetExcludingNullItems(
- alwaysThrowingInstructionDesugaring,
- backportedMethodRewriter,
- desugaredLibraryRetargeter));
+ interfaceMethodRewriter =
+ InterfaceMethodRewriter.create(
+ appView,
+ SetUtils.newImmutableSetExcludingNullItems(
+ alwaysThrowingInstructionDesugaring,
+ backportedMethodRewriter,
+ desugaredLibraryRetargeter));
+ if (interfaceMethodRewriter != null) {
desugarings.add(interfaceMethodRewriter);
- } else {
- interfaceMethodRewriter = null;
}
desugaredLibraryAPIConverter =
appView.typeRewriter.isRewriting()
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/EmulatedInterfaceDescriptor.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/EmulatedInterfaceDescriptor.java
index fb96fe6..fee2962 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/EmulatedInterfaceDescriptor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/EmulatedInterfaceDescriptor.java
@@ -9,6 +9,13 @@
import java.util.Map;
import java.util.Objects;
+/**
+ * An EmulatedInterfaceDescriptor describes how emulated interfaces are desugared. The
+ * emulatedMethods encode the emulated dispatch logic for default methods. Note that there is an
+ * implicit decision here: If interface method desugaring is enabled (< 24), the static methods in
+ * the emulated interface are going to be desugared, else they are left in place. This means static
+ * methods need to be manually retargeted when interface method desugaring is not enabled.
+ */
public class EmulatedInterfaceDescriptor implements SpecificationDescriptor {
private final DexType rewrittenType;
private final Map<DexMethod, EmulatedDispatchMethodDescriptor> emulatedMethods;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LibraryValidator.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LibraryValidator.java
index 567cc79..c6ea5b0 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LibraryValidator.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/LibraryValidator.java
@@ -28,6 +28,8 @@
levelType = app.dexItemFactory.createType("Ljava/util/concurrent/Flow;");
} else if (requiredCompilationAPILevel.isEqualTo(AndroidApiLevel.N)) {
levelType = app.dexItemFactory.createType("Ljava/util/function/Supplier;");
+ } else if (requiredCompilationAPILevel.isEqualTo(AndroidApiLevel.T)) {
+ levelType = app.dexItemFactory.createType("Ljava/lang/invoke/VarHandle;");
} else {
app.options.reporter.warning(
"Unsupported requiredCompilationAPILevel: " + requiredCompilationAPILevel);
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 1682151..eb710e9 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
@@ -4,6 +4,8 @@
package com.android.tools.r8.ir.desugar.itf;
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode.EMULATED_INTERFACE_ONLY;
+
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.cf.code.CfNew;
import com.android.tools.r8.cf.code.CfStackInstruction;
@@ -29,6 +31,7 @@
import com.android.tools.r8.graph.MethodResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.DerivedMethod;
+import com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode;
import com.android.tools.r8.position.MethodPosition;
import com.android.tools.r8.utils.BooleanBox;
import com.android.tools.r8.utils.BooleanUtils;
@@ -374,7 +377,12 @@
private final Map<DexProgramClass, List<ClassTypeSignature>> newExtraInterfaceSignatures =
new ConcurrentHashMap<>();
- ClassProcessor(AppView<?> appView, Predicate<ProgramMethod> isLiveMethod) {
+ private final InterfaceMethodDesugaringMode desugaringMode;
+
+ ClassProcessor(
+ AppView<?> appView,
+ Predicate<ProgramMethod> isLiveMethod,
+ InterfaceMethodDesugaringMode desugaringMode) {
this.appView = appView;
this.dexItemFactory = appView.dexItemFactory();
this.helper = new InterfaceDesugaringSyntheticHelper(appView);
@@ -382,6 +390,7 @@
!appView.options().canUseDefaultAndStaticInterfaceMethods()
&& !appView.options().machineDesugaredLibrarySpecification.isEmpty();
this.isLiveMethod = isLiveMethod;
+ this.desugaringMode = desugaringMode;
}
private boolean isLiveMethod(DexClassAndMethod method) {
@@ -440,6 +449,9 @@
assert iface.isInterface();
assert iface.superType == dexItemFactory.objectType;
assert !helper.isEmulatedInterface(iface.type);
+ if (desugaringMode == EMULATED_INTERFACE_ONLY) {
+ return SignaturesInfo.EMPTY;
+ }
// Add non-library default methods as well as those for desugared library classes.
if (!iface.isLibraryClass() || (needsLibraryInfo() && helper.isInDesugaredLibrary(iface))) {
MethodSignatures signatures = getDefaultMethods(iface);
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 eda530c..4ac2b73 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
@@ -72,6 +72,23 @@
this.shouldIgnoreFromReportsPredicate = getShouldIgnoreFromReportsPredicate(appView);
}
+ public enum InterfaceMethodDesugaringMode {
+ ALL,
+ EMULATED_INTERFACE_ONLY,
+ NONE
+ }
+
+ public static InterfaceMethodDesugaringMode getInterfaceMethodDesugaringMode(
+ InternalOptions options) {
+ if (options.isInterfaceMethodDesugaringEnabled()) {
+ return InterfaceMethodDesugaringMode.ALL;
+ }
+ if (options.machineDesugaredLibrarySpecification.getEmulatedInterfaces().isEmpty()) {
+ return InterfaceMethodDesugaringMode.NONE;
+ }
+ return InterfaceMethodDesugaringMode.EMULATED_INTERFACE_ONLY;
+ }
+
boolean isEmulatedInterface(DexType itf) {
return appView
.options()
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodProcessorFacade.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodProcessorFacade.java
index 434238a..a5ec16a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodProcessorFacade.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodProcessorFacade.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.desugar.CfPostProcessingDesugaring;
import com.android.tools.r8.ir.desugar.CfPostProcessingDesugaringEventConsumer;
+import com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode;
import com.android.tools.r8.ir.desugar.itf.InterfaceMethodRewriter.Flavor;
import com.android.tools.r8.utils.ThreadUtils;
import com.google.common.collect.Iterables;
@@ -28,11 +29,13 @@
AppView<?> appView,
Flavor flavour,
Predicate<ProgramMethod> isLiveMethod,
- InterfaceProcessor interfaceProcessor) {
+ InterfaceProcessor interfaceProcessor,
+ InterfaceMethodDesugaringMode desugaringMode) {
this.appView = appView;
this.flavour = flavour;
+ assert interfaceProcessor != null;
this.interfaceProcessor = interfaceProcessor;
- this.classProcessor = new ClassProcessor(appView, isLiveMethod);
+ this.classProcessor = new ClassProcessor(appView, isLiveMethod, desugaringMode);
}
private boolean shouldProcess(DexProgramClass clazz, Flavor flavour) {
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 955183a..e91925d 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
@@ -4,6 +4,11 @@
package com.android.tools.r8.ir.desugar.itf;
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode.ALL;
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode.EMULATED_INTERFACE_ONLY;
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode.NONE;
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.getInterfaceMethodDesugaringMode;
+
import com.android.tools.r8.DesugarGraphConsumer;
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.cf.code.CfInstruction;
@@ -38,6 +43,7 @@
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.DerivedMethod;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.icce.AlwaysThrowingInstructionDesugaring;
+import com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode;
import com.android.tools.r8.ir.desugar.lambda.LambdaInstructionDesugaring;
import com.android.tools.r8.ir.desugar.stringconcat.StringConcatInstructionDesugaring;
import com.android.tools.r8.ir.synthetic.ForwardMethodBuilder;
@@ -87,6 +93,9 @@
private final AppView<?> appView;
private final InternalOptions options;
final DexItemFactory factory;
+ // If this is true, this will desugar only default methods from emulated interfaces present in
+ // the emulated interface descriptor.
+ private final InterfaceMethodDesugaringMode desugaringMode;
private final InterfaceDesugaringSyntheticHelper helper;
// The emulatedMethod set is there to avoid doing the emulated look-up too often.
private final Set<DexString> emulatedMethods = Sets.newIdentityHashSet();
@@ -108,12 +117,28 @@
ExcludeDexResources
}
- public InterfaceMethodRewriter(
+ public static InterfaceMethodRewriter create(
AppView<?> appView, Set<CfInstructionDesugaring> precedingDesugarings) {
+ InterfaceMethodDesugaringMode desugaringMode =
+ getInterfaceMethodDesugaringMode(appView.options());
+ if (desugaringMode == NONE) {
+ return null;
+ }
+ return new InterfaceMethodRewriter(appView, precedingDesugarings, desugaringMode);
+ }
+
+ public InterfaceMethodRewriter(
+ AppView<?> appView,
+ Set<CfInstructionDesugaring> precedingDesugarings,
+ InterfaceMethodDesugaringMode desugaringMode) {
this.appView = appView;
this.precedingDesugarings = precedingDesugarings;
this.options = appView.options();
this.factory = appView.dexItemFactory();
+ assert desugaringMode == EMULATED_INTERFACE_ONLY || desugaringMode == ALL;
+ this.desugaringMode = desugaringMode;
+ assert desugaringMode == EMULATED_INTERFACE_ONLY
+ || appView.options().isInterfaceMethodDesugaringEnabled();
this.helper = new InterfaceDesugaringSyntheticHelper(appView);
initializeEmulatedInterfaceVariables();
}
@@ -274,15 +299,18 @@
.build();
}
// Continue with invoke type logic.
+ if (invoke.isInvokeVirtual() || invoke.isInvokeInterface()) {
+ return computeInvokeVirtualDispatch(holder, invoke, context);
+ }
+ if (desugaringMode == EMULATED_INTERFACE_ONLY) {
+ return DesugarDescription.nothing();
+ }
if (invoke.isInvokeStatic()) {
return computeInvokeStatic(holder, invoke, context);
}
if (invoke.isInvokeSpecial()) {
return computeInvokeSpecial(holder, invoke, context);
}
- if (invoke.isInvokeVirtual() || invoke.isInvokeInterface()) {
- return computeInvokeVirtualDispatch(holder, invoke, context);
- }
return DesugarDescription.nothing();
}
@@ -839,14 +867,16 @@
public InterfaceMethodProcessorFacade getPostProcessingDesugaringD8(
Flavor flavour, InterfaceProcessor interfaceProcessor) {
- return new InterfaceMethodProcessorFacade(appView, flavour, m -> true, interfaceProcessor);
+ return new InterfaceMethodProcessorFacade(
+ appView, flavour, m -> true, interfaceProcessor, desugaringMode);
}
public InterfaceMethodProcessorFacade getPostProcessingDesugaringR8(
Flavor flavour,
Predicate<ProgramMethod> isLiveMethod,
InterfaceProcessor interfaceProcessor) {
- return new InterfaceMethodProcessorFacade(appView, flavour, isLiveMethod, interfaceProcessor);
+ return new InterfaceMethodProcessorFacade(
+ appView, flavour, isLiveMethod, interfaceProcessor, desugaringMode);
}
private Origin getMethodOrigin(DexMethod method) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
index 59dcd83..8d2c8c6 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
@@ -4,6 +4,10 @@
package com.android.tools.r8.ir.desugar.itf;
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode.EMULATED_INTERFACE_ONLY;
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode.NONE;
+import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.getInterfaceMethodDesugaringMode;
+
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.dex.code.DexInstruction;
@@ -25,6 +29,8 @@
import com.android.tools.r8.graph.MethodCollection;
import com.android.tools.r8.graph.NestedGraphLens;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.EmulatedDispatchMethodDescriptor;
+import com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode;
import com.android.tools.r8.synthesis.SyntheticMethodBuilder;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.collections.BidirectionalManyToManyRepresentativeMap;
@@ -56,10 +62,21 @@
private final InterfaceDesugaringSyntheticHelper helper;
private final Map<DexProgramClass, PostProcessingInterfaceInfo> postProcessingInterfaceInfos =
new ConcurrentHashMap<>();
+ private final InterfaceMethodDesugaringMode desugaringMode;
- public InterfaceProcessor(AppView<?> appView) {
+ public static InterfaceProcessor create(AppView<?> appView) {
+ InterfaceMethodDesugaringMode desugaringMode =
+ getInterfaceMethodDesugaringMode(appView.options());
+ if (desugaringMode == NONE) {
+ return null;
+ }
+ return new InterfaceProcessor(appView, desugaringMode);
+ }
+
+ public InterfaceProcessor(AppView<?> appView, InterfaceMethodDesugaringMode desugaringMode) {
this.appView = appView;
helper = new InterfaceDesugaringSyntheticHelper(appView);
+ this.desugaringMode = desugaringMode;
}
public InterfaceDesugaringSyntheticHelper getHelper() {
@@ -72,6 +89,10 @@
if (!method.getHolder().isInterface()) {
return;
}
+ if (desugaringMode == EMULATED_INTERFACE_ONLY) {
+ processEmulatedInterfaceOnly(method);
+ return;
+ }
if (method.getDefinition().belongsToDirectPool()) {
processDirectInterfaceMethod(method, eventConsumer);
} else {
@@ -83,6 +104,25 @@
}
}
+ private void processEmulatedInterfaceOnly(ProgramMethod method) {
+ if (!appView.options().isDesugaredLibraryCompilation()) {
+ return;
+ }
+ if (method.getDefinition().belongsToDirectPool()) {
+ return;
+ }
+ if (helper.isEmulatedInterface(method.getHolderType())) {
+ EmulatedDispatchMethodDescriptor emulatedDispatchDescriptor =
+ helper.getEmulatedDispatchDescriptor(method.getHolder(), method);
+ if (emulatedDispatchDescriptor != null) {
+ processVirtualInterfaceMethod(method);
+ if (!interfaceMethodRemovalChangesApi(method)) {
+ getPostProcessingInterfaceInfo(method.getHolder()).setHasBridgesToRemove();
+ }
+ }
+ }
+ }
+
static ProgramMethod ensureCompanionMethod(
DexProgramClass iface,
DexString methodName,
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 74202d3..1b77e82 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -510,7 +510,7 @@
liveFields = new LiveFieldsSet(graphReporter::registerField);
if (mode.isInitialTreeShaking()) {
desugaring = CfInstructionDesugaringCollection.create(appView, appView.apiLevelCompute());
- interfaceProcessor = new InterfaceProcessor(appView);
+ interfaceProcessor = InterfaceProcessor.create(appView);
} else {
desugaring = CfInstructionDesugaringCollection.empty();
interfaceProcessor = null;
@@ -4055,6 +4055,7 @@
// Move the pending methods and mark them live and ready for tracing.
for (ProgramMethod method : pendingMethodMove) {
+ assert interfaceProcessor != null;
ProgramMethod companion =
interfaceProcessor
.getHelper()
diff --git a/src/test/examplesJava11/collectiontoarray/Main.java b/src/test/examplesJava11/collectiontoarray/Main.java
new file mode 100644
index 0000000..91bbd8b
--- /dev/null
+++ b/src/test/examplesJava11/collectiontoarray/Main.java
@@ -0,0 +1,20 @@
+// Copyright (c) 2022, 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 collectiontoarray;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class Main {
+ public static void main(String[] args) {
+ List<String> list = new ArrayList<>();
+ list.add("one");
+ list.add("two");
+ // This default method was added in Android T.
+ String[] toArray = list.toArray(String[]::new);
+ System.out.println(Arrays.toString(toArray));
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/CollectionToArrayTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/CollectionToArrayTest.java
new file mode 100644
index 0000000..d3d901a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/CollectionToArrayTest.java
@@ -0,0 +1,63 @@
+// Copyright (c) 2022, 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.desugaredlibrary.jdk11;
+
+import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.DEFAULT_SPECIFICATIONS;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11_PATH;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
+import com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification;
+import com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class CollectionToArrayTest extends DesugaredLibraryTestBase {
+
+ private final TestParameters parameters;
+ private final LibraryDesugaringSpecification libraryDesugaringSpecification;
+ private final CompilationSpecification compilationSpecification;
+
+ private static final Path INPUT_JAR =
+ Paths.get(ToolHelper.EXAMPLES_JAVA11_JAR_DIR + "collectiontoarray.jar");
+ private static final String EXPECTED_OUTPUT = StringUtils.lines("[one, two]");
+ private static final String MAIN_CLASS = "collectiontoarray.Main";
+
+ @Parameters(name = "{0}, spec: {1}, {2}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withDexRuntimes().withAllApiLevels().build(),
+ ImmutableList.of(JDK11, JDK11_PATH),
+ DEFAULT_SPECIFICATIONS);
+ }
+
+ public CollectionToArrayTest(
+ TestParameters parameters,
+ LibraryDesugaringSpecification libraryDesugaringSpecification,
+ CompilationSpecification compilationSpecification) {
+ this.parameters = parameters;
+ this.libraryDesugaringSpecification = libraryDesugaringSpecification;
+ this.compilationSpecification = compilationSpecification;
+ }
+
+ @Test
+ public void test() throws Throwable {
+ testForDesugaredLibrary(parameters, libraryDesugaringSpecification, compilationSpecification)
+ .addProgramFiles(INPUT_JAR)
+ .addKeepMainRule(MAIN_CLASS)
+ .run(parameters.getRuntime(), MAIN_CLASS)
+ .assertSuccessWithOutput(EXPECTED_OUTPUT);
+ }
+}