Version 2.1.83
Add applied field to GraphLens(e) to ensure that we are not rewriting
invoke-interface to default methods int their companion class.
The fix is manually added since this issue has been resolved on other
branches.
Bug: 171982443
Bug: 172895918
Bug: 173184123
Change-Id: I6b0cbe3e4e8715dc38d615e5a5e89e3a7fcf9f7d
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index d2b632d..2b1533f 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
// This field is accessed from release scripts using simple pattern matching.
// Therefore, changing this field could break our release scripts.
- public static final String LABEL = "2.1.82";
+ public static final String LABEL = "2.1.83";
private Version() {
}
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 a277a71..91e03c8 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
@@ -402,6 +402,15 @@
}
@Override
+ public GraphLenseLookupResult lookupMethod(DexMethod method, DexMethod context, Type type) {
+ DexMethod previousContext =
+ originalMethodSignatures != null
+ ? originalMethodSignatures.getOrDefault(context, context)
+ : context;
+ return previousLense.lookupMethod(method, previousContext, type);
+ }
+
+ @Override
protected Type mapInvocationType(DexMethod newMethod, DexMethod originalMethod, Type type) {
return Type.STATIC;
}
diff --git a/src/test/java/com/android/tools/r8/desugar/b171982443/Caller.java b/src/test/java/com/android/tools/r8/desugar/b171982443/Caller.java
new file mode 100644
index 0000000..741cd6d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/b171982443/Caller.java
@@ -0,0 +1,118 @@
+// Copyright (c) 2020, 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.b171982443;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.desugar.b171982443.DefaultMethodInvokeReprocessingTest.I;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+public class Caller implements Opcodes {
+
+ @NeverInline
+ public static void callI(I i) {
+ // We will inline the kotlin function that has kotlin style lambdas. That will trigger
+ // the LambdaMerger and force it to reprocess this method again. That is a problem if we
+ // have desugared I.print() to a default method, since the mapping will be applied for the
+ // i.print() call below
+ i.print();
+ // Since the test cannot reference kotlin code during compilation, we insert the call
+ // manually.
+ // SimpleKt.tBirdTaker();
+ }
+
+ public static byte[] dump() {
+
+ ClassWriter classWriter = new ClassWriter(0);
+ MethodVisitor methodVisitor;
+ AnnotationVisitor annotationVisitor0;
+
+ classWriter.visit(
+ V1_8,
+ ACC_PUBLIC | ACC_SUPER,
+ "com/android/tools/r8/desugar/b171982443/Caller",
+ null,
+ "java/lang/Object",
+ null);
+ classWriter.visitSource("Caller.java", null);
+ classWriter.visitInnerClass(
+ "com/android/tools/r8/desugar/b171982443/DefaultMethodInvokeReprocessingTest$I",
+ "com/android/tools/r8/desugar/b171982443/DefaultMethodInvokeReprocessingTest",
+ "I",
+ ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE);
+
+ {
+ methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ methodVisitor.visitCode();
+ Label label0 = new Label();
+ methodVisitor.visitLabel(label0);
+ methodVisitor.visitLineNumber(10, label0);
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+ methodVisitor.visitInsn(RETURN);
+ Label label1 = new Label();
+ methodVisitor.visitLabel(label1);
+ methodVisitor.visitLocalVariable(
+ "this", "Lcom/android/tools/r8/desugar/b171982443/Caller;", null, label0, label1, 0);
+ methodVisitor.visitMaxs(1, 1);
+ methodVisitor.visitEnd();
+ }
+ {
+ methodVisitor =
+ classWriter.visitMethod(
+ ACC_PUBLIC | ACC_STATIC,
+ "callI",
+ "(Lcom/android/tools/r8/desugar/b171982443/DefaultMethodInvokeReprocessingTest$I;)V",
+ null,
+ null);
+ {
+ annotationVisitor0 =
+ methodVisitor.visitAnnotation("Lcom/android/tools/r8/NeverInline;", false);
+ annotationVisitor0.visitEnd();
+ }
+ methodVisitor.visitCode();
+ Label label0 = new Label();
+ methodVisitor.visitLabel(label0);
+ methodVisitor.visitLineNumber(19, label0);
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitMethodInsn(
+ INVOKEINTERFACE,
+ "com/android/tools/r8/desugar/b171982443/DefaultMethodInvokeReprocessingTest$I",
+ "print",
+ "()V",
+ true);
+ Label label1 = new Label();
+ methodVisitor.visitLabel(label1);
+ methodVisitor.visitLineNumber(22, label1);
+ methodVisitor.visitMethodInsn(
+ INVOKESTATIC,
+ "com/android/tools/r8/desugar/b171982443/SimpleKt",
+ "tBirdTaker",
+ "()V",
+ false);
+ Label label2 = new Label();
+ methodVisitor.visitLabel(label2);
+ methodVisitor.visitLineNumber(23, label2);
+ methodVisitor.visitInsn(RETURN);
+ Label label3 = new Label();
+ methodVisitor.visitLabel(label3);
+ methodVisitor.visitLocalVariable(
+ "i",
+ "Lcom/android/tools/r8/desugar/b171982443/DefaultMethodInvokeReprocessingTest$I;",
+ null,
+ label0,
+ label3,
+ 0);
+ methodVisitor.visitMaxs(1, 1);
+ methodVisitor.visitEnd();
+ }
+ classWriter.visitEnd();
+
+ return classWriter.toByteArray();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/b171982443/DefaultMethodInvokeReprocessingTest.java b/src/test/java/com/android/tools/r8/desugar/b171982443/DefaultMethodInvokeReprocessingTest.java
new file mode 100644
index 0000000..5c2f0d3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/b171982443/DefaultMethodInvokeReprocessingTest.java
@@ -0,0 +1,114 @@
+// Copyright (c) 2020, 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.b171982443;
+
+import static com.android.tools.r8.KotlinCompilerTool.KOTLINC;
+import static com.android.tools.r8.desugar.b171982443.Caller.callI;
+import static org.hamcrest.CoreMatchers.equalTo;
+
+import com.android.tools.r8.KotlinTestBase;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
+import com.android.tools.r8.utils.DescriptorUtils;
+import java.nio.file.Path;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+// This is a reproduction of b/171982443.
+@RunWith(Parameterized.class)
+public class DefaultMethodInvokeReprocessingTest extends KotlinTestBase {
+
+ private static final String PKG =
+ DefaultMethodInvokeReprocessingTest.class.getPackage().getName();
+ private static final String PKG_PREFIX = DescriptorUtils.getBinaryNameFromJavaType(PKG);
+ private static final String[] EXPECTED = new String[] {"A::foo", "Hello1", "Hello2", "Hello3"};
+ private final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withDexRuntimes().withAllApiLevels().build(),
+ KotlinTargetVersion.values());
+ }
+
+ public DefaultMethodInvokeReprocessingTest(
+ TestParameters parameters, KotlinTargetVersion targetVersion) {
+ super(targetVersion);
+ this.parameters = parameters;
+ }
+
+ private static final Map<KotlinTargetVersion, Path> libJarMap = new HashMap<>();
+
+ @BeforeClass
+ public static void createLibJar() throws Exception {
+ for (KotlinTargetVersion kotlinTargetVersion : KotlinTargetVersion.values()) {
+ libJarMap.put(
+ kotlinTargetVersion,
+ kotlinc(KOTLINC, kotlinTargetVersion)
+ .addSourceFiles(getKotlinFileInTest(PKG_PREFIX, "Simple"))
+ .compile());
+ }
+ }
+
+ @Test
+ public void testRuntime() throws Exception {
+ testForRuntime(parameters)
+ .addInnerClasses(DefaultMethodInvokeReprocessingTest.class)
+ .addProgramClassFileData(Caller.dump())
+ .addProgramFiles(ToolHelper.getKotlinStdlibJar())
+ .addProgramFiles(libJarMap.get(targetVersion))
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(EXPECTED);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(DefaultMethodInvokeReprocessingTest.class)
+ .addProgramFiles(libJarMap.get(targetVersion))
+ .addProgramFiles(ToolHelper.getKotlinStdlibJar())
+ .addProgramClassFileData(Caller.dump())
+ .setMinApi(parameters.getApiLevel())
+ .addKeepMainRule(Main.class)
+ .addKeepClassAndMembersRules(I.class)
+ .enableInliningAnnotations()
+ .allowDiagnosticWarningMessages()
+ .compile()
+ .assertAllWarningMessagesMatch(equalTo("Resource 'META-INF/MANIFEST.MF' already exists."))
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(EXPECTED);
+ }
+
+ public interface I {
+
+ default void print() {
+ System.out.println("I::foo");
+ }
+ }
+
+ public static class A implements I {
+
+ @Override
+ @NeverInline
+ public void print() {
+ System.out.println("A::foo");
+ }
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ callI(args.length == 0 ? new A() : new I() {});
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/b171982443/Simple.kt b/src/test/java/com/android/tools/r8/desugar/b171982443/Simple.kt
new file mode 100644
index 0000000..c0df2d4
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/b171982443/Simple.kt
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, 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.b171982443
+
+fun runSimple(cb: () -> Unit) {
+ cb()
+}
+
+fun tBirdTaker() {
+ runSimple { println("Hello1")}
+ runSimple { println("Hello2")}
+ runSimple { println("Hello3")}
+}
\ No newline at end of file