Account for dynamic null receiver type in argument propagation
Bug: b/250634405
Change-Id: I4d29c793951f11189ae7954380d72a3b056027f3
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorCodeScanner.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorCodeScanner.java
index eff76c7..9023c00 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorCodeScanner.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorCodeScanner.java
@@ -284,7 +284,13 @@
ProgramMethod context,
ConcretePolymorphicMethodStateOrBottom existingMethodState) {
DynamicTypeWithUpperBound dynamicReceiverType = invoke.getReceiver().getDynamicType(appView);
- assert !dynamicReceiverType.getDynamicUpperBoundType().nullability().isDefinitelyNull();
+ if (dynamicReceiverType.isNullType()) {
+ // This can happen if we were unable to determine that the receiver is a phi value where null
+ // information has not been propagated down. See if we can improve the test here or ensure
+ // that all phi's are normalized before computing the optimization info.
+ assert appView.checkForTesting(() -> false) : "b/250634405";
+ return MethodState.unknown();
+ }
ProgramMethod singleTarget = invoke.lookupSingleProgramTarget(appView, context);
DynamicTypeWithUpperBound bounds =
diff --git a/src/test/java/com/android/tools/r8/optimize/argumentpropagation/PolymorphicMethodWithNullReceiverBoundTest.java b/src/test/java/com/android/tools/r8/optimize/argumentpropagation/PolymorphicMethodWithNullReceiverBoundTest.java
index 5b09e47..5ad2a81 100644
--- a/src/test/java/com/android/tools/r8/optimize/argumentpropagation/PolymorphicMethodWithNullReceiverBoundTest.java
+++ b/src/test/java/com/android/tools/r8/optimize/argumentpropagation/PolymorphicMethodWithNullReceiverBoundTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.optimize.argumentpropagation;
+import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertThrows;
import com.android.tools.r8.CompilationFailedException;
@@ -40,24 +41,45 @@
}
@Test
- public void test() throws Exception {
- // TODO(b/250634405): Check for null in dynamic receiver type.
+ public void testR8WithTestAssertionsEnabled() {
assertThrows(
CompilationFailedException.class,
- () ->
- testForR8(parameters.getBackend())
- .addInnerClasses(getClass())
- .addKeepMainRule(Main.class)
- .enableNoHorizontalClassMergingAnnotations()
- .enableNoVerticalClassMergingAnnotations()
- .setMinApi(parameters.getApiLevel())
- .addOptionsModification(
- options -> {
- options.testing.cfByteCodePassThrough =
- method -> method.getName().startsWith("main");
- options.testing.checkReceiverAlwaysNullInCallSiteOptimization = false;
- })
- .compile());
+ () -> {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .enableNoHorizontalClassMergingAnnotations()
+ .enableNoVerticalClassMergingAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .addOptionsModification(
+ options -> {
+ options.testing.cfByteCodePassThrough =
+ method -> method.getName().startsWith("main");
+ options.testing.checkReceiverAlwaysNullInCallSiteOptimization = false;
+ })
+ .compileWithExpectedDiagnostics(
+ diagnostics -> {
+ diagnostics.assertErrorMessageThatMatches(containsString("b/250634405"));
+ });
+ });
+ }
+
+ @Test
+ public void testR8WithoutTestAssertions() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .enableNoHorizontalClassMergingAnnotations()
+ .enableNoVerticalClassMergingAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .addOptionsModification(
+ options -> {
+ options.testing.cfByteCodePassThrough = method -> method.getName().startsWith("main");
+ options.testing.checkReceiverAlwaysNullInCallSiteOptimization = false;
+ options.testing.enableTestAssertions = false;
+ })
+ .run(parameters.getRuntime(), Main.class)
+ .assertFailureWithErrorThatThrows(NullPointerException.class);
}
static class Main {