Fix assertion errors when building dump

Change-Id: I08397b15a27d47b2be2b6994933116266fe3344d
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java
index 791577a..9eeb1f9 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.ir.analysis.type;
 
+import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexMethod;
@@ -30,6 +31,7 @@
     WIDENING,  // initial analysis, including fixed-point iteration for phis and updating with less
                // specific info, e.g., removing assume nodes.
     NARROWING, // updating with more specific info, e.g., passing the return value of the inlinee.
+    PROPAGATE, // effectively NARROWING_OR_WIDENING
     NO_CHANGE  // utility to ensure types are up to date
   }
 
@@ -100,6 +102,20 @@
     removeRedundantAssumeInstructions(redundantAssumeConsumer);
   }
 
+  public void propagate(Iterable<? extends Value> values) {
+    analyzeValues(values, Mode.PROPAGATE);
+  }
+
+  public void propagateWithAssumeRemoval(Iterable<? extends Value> values) {
+    propagateWithAssumeRemoval(values, ConsumerUtils.emptyConsumer());
+  }
+
+  public void propagateWithAssumeRemoval(
+      Iterable<? extends Value> values, Consumer<Assume> redundantAssumeConsumer) {
+    propagate(values);
+    removeRedundantAssumeInstructions(redundantAssumeConsumer);
+  }
+
   private void removeRedundantAssumeInstructions(Consumer<Assume> redundantAssumeConsumer) {
     Set<Value> affectedValuesFromAssumeRemoval = Sets.newIdentityHashSet();
     while (assumeRemover.removeRedundantAssumeInstructions(
@@ -204,11 +220,18 @@
       return;
     }
 
-    if (mode == Mode.WIDENING) {
-      value.widening(appView, type);
-    } else {
-      assert mode == Mode.NARROWING;
-      value.narrowing(appView, code.context(), type);
+    switch (mode) {
+      case NARROWING:
+        value.narrowing(appView, code.context(), type);
+        break;
+      case PROPAGATE:
+        value.setType(type);
+        break;
+      case WIDENING:
+        value.widening(appView, type);
+        break;
+      default:
+        throw new Unreachable();
     }
 
     // propagate the type change to (instruction) users if any.
diff --git a/src/main/java/com/android/tools/r8/ir/code/Return.java b/src/main/java/com/android/tools/r8/ir/code/Return.java
index 1efb557..4e89ab8 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Return.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Return.java
@@ -122,7 +122,10 @@
   @Override
   public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, ProgramMethod context) {
-    return inliningConstraints.forReturn();
+    if (hasReturnValue()) {
+      return inliningConstraints.forReturn(returnValue().getType(), context);
+    }
+    return inliningConstraints.forReturnVoid();
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/passes/TrivialCheckCastAndInstanceOfRemover.java b/src/main/java/com/android/tools/r8/ir/conversion/passes/TrivialCheckCastAndInstanceOfRemover.java
index 4f42153..9e18843 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/passes/TrivialCheckCastAndInstanceOfRemover.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/passes/TrivialCheckCastAndInstanceOfRemover.java
@@ -97,15 +97,23 @@
                   methodProcessor,
                   methodProcessingContext);
           if (removeResult != RemoveCheckCastInstructionIfTrivialResult.NO_REMOVALS) {
-            assert removeResult == RemoveCheckCastInstructionIfTrivialResult.REMOVED_CAST_DO_NARROW;
             hasChanged = true;
             needToRemoveTrivialPhis |= hasPhiUsers;
             int blockSizeBeforeAssumeRemoval = block.size();
             Instruction previous = it.peekPrevious();
-            affectedValues.narrowingWithAssumeRemoval(
-                appView,
-                code,
-                typeAnalysis -> typeAnalysis.setKeepRedundantBlocksAfterAssumeRemoval(true));
+            if (removeResult == RemoveCheckCastInstructionIfTrivialResult.REMOVED_CAST_DO_NARROW) {
+              affectedValues.narrowingWithAssumeRemoval(
+                  appView,
+                  code,
+                  typeAnalysis -> typeAnalysis.setKeepRedundantBlocksAfterAssumeRemoval(true));
+            } else {
+              assert removeResult
+                  == RemoveCheckCastInstructionIfTrivialResult.REMOVED_CAST_DO_PROPAGATE;
+              affectedValues.propagateWithAssumeRemoval(
+                  appView,
+                  code,
+                  typeAnalysis -> typeAnalysis.setKeepRedundantBlocksAfterAssumeRemoval(true));
+            }
             if (block.size() != blockSizeBeforeAssumeRemoval) {
               it = previous != null ? block.listIterator(code, previous) : block.listIterator(code);
             }
@@ -142,7 +150,8 @@
 
   enum RemoveCheckCastInstructionIfTrivialResult {
     NO_REMOVALS,
-    REMOVED_CAST_DO_NARROW
+    REMOVED_CAST_DO_NARROW,
+    REMOVED_CAST_DO_PROPAGATE
   }
 
   private enum InstanceOfResult {
@@ -264,7 +273,10 @@
               .build();
       it.replaceCurrentInstruction(replacement);
       assert replacement.lookupSingleTarget(appView, context) != null;
-      return RemoveCheckCastInstructionIfTrivialResult.REMOVED_CAST_DO_NARROW;
+      if (checkCast.object().getType().isNullable()) {
+        return RemoveCheckCastInstructionIfTrivialResult.REMOVED_CAST_DO_NARROW;
+      }
+      return RemoveCheckCastInstructionIfTrivialResult.REMOVED_CAST_DO_PROPAGATE;
     }
 
     // If the cast is guaranteed to succeed and only there to ensure the program type checks, then
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/AffectedValues.java b/src/main/java/com/android/tools/r8/ir/optimize/AffectedValues.java
index 681eb9e..2258b27 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/AffectedValues.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/AffectedValues.java
@@ -51,6 +51,16 @@
     }
   }
 
+  public void propagateWithAssumeRemoval(
+      AppView<?> appView, IRCode code, Consumer<TypeAnalysis> typeAnalysisConsumer) {
+    if (hasNext()) {
+      TypeAnalysis typeAnalysis = new TypeAnalysis(appView, code);
+      typeAnalysisConsumer.accept(typeAnalysis);
+      typeAnalysis.propagateWithAssumeRemoval(this);
+      clear();
+    }
+  }
+
   public void widening(AppView<?> appView, IRCode code) {
     if (hasNext()) {
       new TypeAnalysis(appView, code).widening(this);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
index 8f61ce7..a9a29a2 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
@@ -17,6 +17,7 @@
 import com.android.tools.r8.graph.FieldResolutionResult.SingleFieldResolutionResult;
 import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
 import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
 import com.android.tools.r8.ir.code.InvokeType;
 import com.android.tools.r8.ir.optimize.Inliner.Constraint;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
@@ -244,7 +245,15 @@
     return ConstraintWithTarget.ALWAYS;
   }
 
-  public ConstraintWithTarget forReturn() {
+  public ConstraintWithTarget forReturn(TypeElement returnType, ProgramMethod context) {
+    // If the return value is not an instance of the static return type, then do not inline.
+    if (returnType.lessThanOrEqual(context.getReturnType().toTypeElement(appView), appView)) {
+      return ConstraintWithTarget.ALWAYS;
+    }
+    return ConstraintWithTarget.NEVER;
+  }
+
+  public ConstraintWithTarget forReturnVoid() {
     return ConstraintWithTarget.ALWAYS;
   }