Fix inadequate type propagation in EnumValueOptimizer

Change-Id: Ib81ae2947d59e6f290385691a2f2f025834666bf
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstString.java b/src/main/java/com/android/tools/r8/ir/code/ConstString.java
index 3bd1d56..6f0fe00 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstString.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstString.java
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.ir.code;
 
+import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
+
 import com.android.tools.r8.cf.LoadStoreHelper;
 import com.android.tools.r8.cf.TypeVerificationHelper;
 import com.android.tools.r8.cf.code.CfConstString;
@@ -11,7 +13,6 @@
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.ir.analysis.type.Nullability;
 import com.android.tools.r8.ir.analysis.type.TypeElement;
 import com.android.tools.r8.ir.analysis.value.AbstractValue;
 import com.android.tools.r8.ir.analysis.value.UnknownValue;
@@ -154,7 +155,7 @@
 
   @Override
   public TypeElement evaluate(AppView<?> appView) {
-    return TypeElement.stringClassType(appView, Nullability.definitelyNotNull());
+    return TypeElement.stringClassType(appView, definitelyNotNull());
   }
 
   @Override
@@ -170,4 +171,12 @@
     }
     return UnknownValue.getInstance();
   }
+
+  @Override
+  public boolean verifyTypes(AppView<?> appView) {
+    assert super.verifyTypes(appView);
+    TypeElement expectedType = TypeElement.stringClassType(appView, definitelyNotNull());
+    assert getOutType().equals(expectedType);
+    return true;
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
index 8f83953..2cd8633 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
@@ -4,6 +4,8 @@
 
 package com.android.tools.r8.ir.optimize.enums;
 
+import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
+
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedMethod;
@@ -15,6 +17,7 @@
 import com.android.tools.r8.graph.EnumValueInfoMapCollection.EnumValueInfo;
 import com.android.tools.r8.graph.EnumValueInfoMapCollection.EnumValueInfoMap;
 import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
 import com.android.tools.r8.ir.code.ArrayGet;
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
@@ -61,6 +64,7 @@
       return;
     }
 
+    Set<Value> affectedValues = Sets.newIdentityHashSet();
     InstructionListIterator iterator = code.instructionListIterator();
     while (iterator.hasNext()) {
       Instruction current = iterator.next();
@@ -103,8 +107,12 @@
         if (isOrdinalInvoke) {
           iterator.replaceCurrentInstruction(new ConstNumber(outValue, valueInfo.ordinal));
         } else if (isNameInvoke) {
+          Value newValue =
+              code.createValue(TypeElement.stringClassType(appView, definitelyNotNull()));
           iterator.replaceCurrentInstruction(
-              new ConstString(outValue, enumField.name, ThrowingInfo.NO_THROW));
+              new ConstString(
+                  newValue, enumField.name, ThrowingInfo.defaultForConstString(appView.options())));
+          newValue.addAffectedValuesTo(affectedValues);
         } else {
           assert isToStringInvoke;
           DexClass enumClazz = appView.appInfo().definitionFor(enumField.type);
@@ -119,8 +127,12 @@
           if (singleTarget != null && singleTarget.method != factory.enumMethods.toString) {
             continue;
           }
+          Value newValue =
+              code.createValue(TypeElement.stringClassType(appView, definitelyNotNull()));
           iterator.replaceCurrentInstruction(
-              new ConstString(outValue, enumField.name, ThrowingInfo.NO_THROW));
+              new ConstString(
+                  newValue, enumField.name, ThrowingInfo.defaultForConstString(appView.options())));
+          newValue.addAffectedValuesTo(affectedValues);
         }
       } else if (current.isArrayLength()) {
         // Rewrites MyEnum.values().length to a constant int.
@@ -140,6 +152,9 @@
         }
       }
     }
+    if (!affectedValues.isEmpty()) {
+      new TypeAnalysis(appView).narrowing(affectedValues);
+    }
     assert code.isConsistentSSA();
   }