Fix instanceGet on null

Change-Id: I67f64bb69af49c21f1b5f8c09a0acb081e339d58
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
index fa88164..867c2dc 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
@@ -387,11 +387,15 @@
             Value rewrittenOutValue =
                 code.createValue(
                     TypeElement.fromDexType(fieldMethod.getReturnType(), maybeNull(), appView));
+            Value in = instanceGet.object();
+            if (in.getType().isNullType()) {
+              iterator.previous();
+              in = iterator.insertConstIntInstruction(code, options, 0);
+              iterator.next();
+            }
             InvokeStatic invoke =
                 new InvokeStatic(
-                    fieldMethod.getReference(),
-                    rewrittenOutValue,
-                    ImmutableList.of(instanceGet.object()));
+                    fieldMethod.getReference(), rewrittenOutValue, ImmutableList.of(in));
             iterator.replaceCurrentInstruction(invoke);
             if (unboxedEnumsData.isUnboxedEnum(instanceGet.getField().type)) {
               convertedEnums.put(invoke, instanceGet.getField().type);
@@ -529,6 +533,8 @@
       if (invokedMethod == factory.javaLangSystemMembers.arraycopy) {
         // Intentionally empty.
       } else if (invokedMethod == factory.javaLangSystemMembers.identityHashCode) {
+        // Note that System.identityHashCode(null) == 0, so it works even if the input is null
+        // and not rewritten.
         assert invoke.arguments().size() == 1;
         Value argument = invoke.getFirstArgument();
         DexType enumType = getEnumClassTypeOrNull(argument, convertedEnums);
diff --git a/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxNullArgumentTest.java b/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxNullArgumentTest.java
index c55ecf6..1f0492d 100644
--- a/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxNullArgumentTest.java
+++ b/src/test/java/com/android/tools/r8/enumunboxing/EnumUnboxNullArgumentTest.java
@@ -4,10 +4,6 @@
 
 package com.android.tools.r8.enumunboxing;
 
-import static org.hamcrest.CoreMatchers.containsString;
-import static org.junit.Assert.assertThrows;
-
-import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
@@ -29,24 +25,14 @@
   }
 
   @Test
-  public void testR8() {
-    // TODO(b/287193321): We should not fail compilation.
-    assertThrows(
-        CompilationFailedException.class,
-        () ->
-            testForR8(parameters.getBackend())
-                .addInnerClasses(getClass())
-                .setMinApi(parameters)
-                .addKeepMainRule(Main.class)
-                // TODO(b/287193321): Using LIR avoids the issue, is it fixed or just hidden?
-                .addOptionsModification(options -> options.testing.disableLir())
-                .compileWithExpectedDiagnostics(
-                    diagnostics -> {
-                      if (parameters.isDexRuntime()) {
-                        diagnostics.assertErrorMessageThatMatches(
-                            containsString("Cannot constrain type"));
-                      }
-                    }));
+  public void testR8() throws Exception {
+    testForR8(parameters.getBackend())
+        .addInnerClasses(getClass())
+        .setMinApi(parameters)
+        .addKeepMainRule(Main.class)
+        .addOptionsModification(options -> options.testing.disableLir())
+        .run(parameters.getRuntime(), Main.class)
+        .assertFailureWithErrorThatThrows(NullPointerException.class);
   }
 
   public enum MyEnum {