Make sure desugaring already publicize private methods in interfaces.
Bug: 72109068
Change-Id: I131c054b948043f49ab06e35fd86b3edb4b134ed
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 026c2b5..d234702 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -155,6 +155,9 @@
return isVirtualMethod() && !accessFlags.isAbstract();
}
+ public boolean isPublicMethod() {
+ return accessFlags.isPublic();
+ }
public boolean isPrivateMethod() {
return accessFlags.isPrivate();
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
index 73c5118..76a80d4 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -66,7 +66,7 @@
// Public for testing.
public static final String COMPANION_CLASS_NAME_SUFFIX = "$-CC";
public static final String DEFAULT_METHOD_PREFIX = "$default$";
- private static final String PRIVATE_METHOD_PREFIX = "$private$";
+ public static final String PRIVATE_METHOD_PREFIX = "$private$";
private final IRConverter converter;
private final InternalOptions options;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
index 1e8d57a..f4a76e6 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
@@ -91,7 +91,7 @@
remainingMethods.clear();
// Process static and private methods, move them into companion class as well,
- // make private instance methods static.
+ // make private instance methods public static.
for (DexEncodedMethod direct : iface.directMethods()) {
MethodAccessFlags originalFlags = direct.accessFlags;
MethodAccessFlags newFlags = originalFlags.copy();
diff --git a/src/test/java/com/android/tools/r8/RunExamplesJava9Test.java b/src/test/java/com/android/tools/r8/RunExamplesJava9Test.java
index 9560c1f..60ebf39 100644
--- a/src/test/java/com/android/tools/r8/RunExamplesJava9Test.java
+++ b/src/test/java/com/android/tools/r8/RunExamplesJava9Test.java
@@ -4,28 +4,28 @@
package com.android.tools.r8;
+import static com.android.tools.r8.utils.DexInspectorMatchers.isPresent;
import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
import static com.android.tools.r8.utils.FileUtils.ZIP_EXTENSION;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.ToolHelper.DexVm;
-import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.ir.desugar.InterfaceMethodRewriter;
import com.android.tools.r8.utils.AndroidApiLevel;
-import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.DexInspector;
+import com.android.tools.r8.utils.DexInspector.ClassSubject;
import com.android.tools.r8.utils.DexInspector.FoundClassSubject;
import com.android.tools.r8.utils.DexInspector.FoundMethodSubject;
import com.android.tools.r8.utils.DexInspector.InstructionSubject;
+import com.android.tools.r8.utils.DexInspector.MethodSubject;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.OffOrAuto;
import com.android.tools.r8.utils.TestDescriptionWatcher;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import com.google.common.io.ByteStreams;
import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
@@ -33,20 +33,17 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
-import java.util.zip.ZipException;
-import java.util.zip.ZipFile;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
public abstract class RunExamplesJava9Test
- <B extends BaseCommand.Builder<? extends BaseCommand, B>> {
+ <B extends BaseCommand.Builder<? extends BaseCommand, B>> {
static final String EXAMPLE_DIR = ToolHelper.EXAMPLES_JAVA9_BUILD_DIR;
abstract class TestRunner<C extends TestRunner<C>> {
@@ -99,10 +96,6 @@
return self();
}
- C withMainDexClass(String... classes) {
- return withBuilderTransformation(builder -> builder.addMainDexClasses(classes));
- }
-
C withInterfaceMethodDesugaring(OffOrAuto behavior) {
return withOptionConsumer(o -> o.interfaceMethodDesugaring = behavior);
}
@@ -111,15 +104,19 @@
return withOptionConsumer(o -> o.tryWithResourcesDesugaring = behavior);
}
+ void combinedOptionConsumer(InternalOptions options) {
+ for (Consumer<InternalOptions> consumer : optionConsumers) {
+ consumer.accept(options);
+ }
+ }
+
C withBuilderTransformation(UnaryOperator<B> builderTransformation) {
builderTransformations.add(builderTransformation);
return self();
}
- void combinedOptionConsumer(InternalOptions options) {
- for (Consumer<InternalOptions> consumer : optionConsumers) {
- consumer.accept(options);
- }
+ C withMainDexClass(String... classes) {
+ return withBuilderTransformation(builder -> builder.addMainDexClasses(classes));
}
Path build() throws Throwable {
@@ -179,19 +176,19 @@
ImmutableMap.Builder<DexVm.Version, List<String>> builder = ImmutableMap.builder();
builder
.put(DexVm.Version.V4_0_4, ImmutableList.of(
- "native-private-interface-methods",// Dex version not supported
+ "native-private-interface-methods", // Dex version not supported
"varhandle"
))
.put(DexVm.Version.V4_4_4, ImmutableList.of(
- "native-private-interface-methods",// Dex version not supported
+ "native-private-interface-methods", // Dex version not supported
"varhandle"
))
.put(DexVm.Version.V5_1_1, ImmutableList.of(
- "native-private-interface-methods",// Dex version not supported
+ "native-private-interface-methods", // Dex version not supported
"varhandle"
))
- .put(DexVm.Version.V6_0_1, ImmutableList.of("native-private-interface-methods",
- // Dex version not supported
+ .put(DexVm.Version.V6_0_1, ImmutableList.of(
+ "native-private-interface-methods", // Dex version not supported
"varhandle"
))
.put(DexVm.Version.V7_0_0, ImmutableList.of(
@@ -208,12 +205,14 @@
// Defines methods failing on JVM, specifies the output to be used for comparison.
private static Map<String, String> expectedJvmResult =
ImmutableMap.of(
- "native-private-interface-methods", "0: s>i>a\n"
+ "native-private-interface-methods",
+ "0: s>i>a\n"
+ "1: d>i>s>i>a\n"
+ "2: l>i>s>i>a\n"
+ "3: x>s\n"
+ "4: c>d>i>s>i>a\n",
- "desugared-private-interface-methods", "0: s>i>a\n"
+ "desugared-private-interface-methods",
+ "0: s>i>a\n"
+ "1: d>i>s>i>a\n"
+ "2: l>i>s>i>a\n"
+ "3: x>s\n"
@@ -245,21 +244,34 @@
@Test
public void nativePrivateInterfaceMethods() throws Throwable {
- test("native-private-interface-methods", "privateinterfacemethods", "PrivateInterfaceMethods")
+ test("native-private-interface-methods",
+ "privateinterfacemethods", "PrivateInterfaceMethods")
.withMinApiLevel(AndroidApiLevel.N.getLevel())
.run();
}
@Test
public void desugaredPrivateInterfaceMethods() throws Throwable {
- test("desugared-private-interface-methods", "privateinterfacemethods",
- "PrivateInterfaceMethods")
+ final String iName = "privateinterfacemethods.I";
+ test("desugared-private-interface-methods",
+ "privateinterfacemethods", "PrivateInterfaceMethods")
.withMinApiLevel(AndroidApiLevel.M.getLevel())
+ .withDexCheck(dexInspector -> {
+ ClassSubject companion = dexInspector.clazz(
+ iName + InterfaceMethodRewriter.COMPANION_CLASS_NAME_SUFFIX);
+ assertThat(companion, isPresent());
+ MethodSubject iFoo = companion.method(
+ "java.lang.String",
+ InterfaceMethodRewriter.PRIVATE_METHOD_PREFIX + "iFoo",
+ ImmutableList.of(iName, "boolean"));
+ assertThat(iFoo, isPresent());
+ assertTrue(iFoo.getMethod().isPublicMethod());
+ })
.run();
}
@Test
- public void varHAndle() throws Throwable {
+ public void varHandle() throws Throwable {
test("varhandle", "varhandle", "VarHandleTests")
.withMinApiLevel(AndroidApiLevel.P.getLevel())
.run();
@@ -285,7 +297,7 @@
thrown.expect(Throwable.class);
}
String output = ToolHelper.runArtNoVerificationErrors(
- Arrays.stream(dexes).map(path -> path.toString()).collect(Collectors.toList()),
+ Arrays.stream(dexes).map(Path::toString).collect(Collectors.toList()),
qualifiedMainClass,
null);
String jvmResult = null;
@@ -308,17 +320,4 @@
}
}
- protected DexInspector getMainDexInspector(Path zip)
- throws ZipException, IOException, ExecutionException {
- try (ZipFile zipFile = new ZipFile(zip.toFile(), StandardCharsets.UTF_8)) {
- try (InputStream in =
- zipFile.getInputStream(zipFile.getEntry(ToolHelper.DEFAULT_DEX_FILENAME))) {
- return new DexInspector(
- AndroidApp.builder()
- .addDexProgramData(ByteStreams.toByteArray(in), Origin.unknown())
- .build());
- }
- }
- }
-
-}
+}
\ No newline at end of file