Use the null type for methods that are guaranteed to return null

Change-Id: I1bfc574e615c3c65e4c61b9ee7b37643b49db829
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/AssumeInserter.java b/src/main/java/com/android/tools/r8/ir/optimize/AssumeInserter.java
index 6477221..0008896 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/AssumeInserter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/AssumeInserter.java
@@ -691,7 +691,7 @@
 
     boolean isNull() {
       return dynamicTypeAssumption != null
-          && dynamicTypeAssumption.getDynamicUpperBoundType().isNullType();
+          && dynamicTypeAssumption.getDynamicUpperBoundType().isDefinitelyNull();
     }
 
     boolean isNonNull() {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
index cd2cc68c..9e270af 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
@@ -956,13 +956,20 @@
       TypeElement dynamicUpperBoundReturnType =
           dynamicTypeOptimization.computeDynamicReturnType(method, code);
       if (dynamicUpperBoundReturnType != null) {
-        TypeElement staticReturnType =
-            TypeElement.fromDexType(staticReturnTypeRaw, Nullability.maybeNull(), appView);
-        // If the dynamic return type is not more precise than the static return type there is no
-        // need to record it.
-        if (dynamicUpperBoundReturnType.strictlyLessThan(staticReturnType, appView)) {
-          feedback.methodReturnsObjectWithUpperBoundType(
-              method, appView, dynamicUpperBoundReturnType);
+        if (dynamicUpperBoundReturnType.isReferenceType()
+            && dynamicUpperBoundReturnType.isDefinitelyNull()) {
+          feedback.methodReturnsAbstractValue(
+              method, appView, appView.abstractValueFactory().createSingleNumberValue(0));
+          feedback.methodReturnsObjectWithUpperBoundType(method, appView, TypeElement.getNull());
+        } else {
+          TypeElement staticReturnType =
+              TypeElement.fromDexType(staticReturnTypeRaw, Nullability.maybeNull(), appView);
+          // If the dynamic return type is not more precise than the static return type there is no
+          // need to record it.
+          if (dynamicUpperBoundReturnType.strictlyLessThan(staticReturnType, appView)) {
+            feedback.methodReturnsObjectWithUpperBoundType(
+                method, appView, dynamicUpperBoundReturnType);
+          }
         }
       }