Fix invoke-virtual to interface after interface merging
Bug: b/320824618
Change-Id: I0e56e2f284557dbc0318bda9adb54c90c7cd899b
diff --git a/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMergerGraphLens.java b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMergerGraphLens.java
index 3987216..c9bc89b 100644
--- a/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMergerGraphLens.java
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMergerGraphLens.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.classmerging.ClassMergerGraphLens;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
@@ -283,7 +284,10 @@
}
if (type.isInterface()
&& mergedClasses.hasInterfaceBeenMergedIntoClass(previousMethod.getHolderType())) {
- return InvokeType.VIRTUAL;
+ DexClass newMethodHolder = appView.definitionForHolder(newMethod);
+ if (newMethodHolder != null && !newMethodHolder.isInterface()) {
+ return InvokeType.VIRTUAL;
+ }
}
return type;
}
diff --git a/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergerInvokeVirtualToInterfaceTest.java b/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergerInvokeVirtualToInterfaceTest.java
index 797ae11..2a8fa07 100644
--- a/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergerInvokeVirtualToInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergerInvokeVirtualToInterfaceTest.java
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.classmerging.vertical;
-import static com.android.tools.r8.utils.codeinspector.AssertUtils.assertFailsCompilation;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
@@ -32,21 +31,20 @@
@Test
public void test() throws Exception {
- assertFailsCompilation(
- () ->
- testForR8(parameters.getBackend())
- .addInnerClasses(getClass())
- .addKeepMainRule(Main.class)
- .addVerticallyMergedClassesInspector(
- inspector ->
- inspector.assertMergedIntoSubtype(J.class).assertNoOtherClassesMerged())
- .enableInliningAnnotations()
- .enableNeverClassInliningAnnotations()
- .enableNoParameterTypeStrengtheningAnnotations()
- .enableNoUnusedInterfaceRemovalAnnotations()
- .enableNoVerticalClassMergingAnnotations()
- .setMinApi(parameters)
- .compile());
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .addVerticallyMergedClassesInspector(
+ inspector -> inspector.assertMergedIntoSubtype(J.class).assertNoOtherClassesMerged())
+ .enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .enableNoParameterTypeStrengtheningAnnotations()
+ .enableNoUnusedInterfaceRemovalAnnotations()
+ .enableNoVerticalClassMergingAnnotations()
+ .setMinApi(parameters)
+ .compile()
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("Hello, world!", "Hello, world!");
}
static class Main {