Recognize reflective instantiation in the presence of debug local write

This would trigger us to correctly see the instantiation in release
mode but not in debug mode.

Bug: 241478253
Change-Id: I851fb9364824b760cb6a1350be4d32ae8e99ccb5
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstantValueUtils.java b/src/main/java/com/android/tools/r8/ir/code/ConstantValueUtils.java
index 86d04e5..9855ee6 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstantValueUtils.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstantValueUtils.java
@@ -13,11 +13,12 @@
 
   /**
    * If the given value is a constant class, then returns the corresponding {@link DexType}.
-   * Otherwise returns null.
+   * Otherwise returns null. This should only be used for tracing.
    */
-  public static DexType getDexTypeRepresentedByValue(
+  public static DexType getDexTypeRepresentedByValueForTracing(
       Value value, DexDefinitionSupplier definitions) {
-    Value alias = value.getAliasedValue();
+    Value alias =
+        value.getAliasedValue(IgnoreDebugLocalWriteAliasedValueConfiguration.getInstance());
     if (alias.isPhi()) {
       return null;
     }
diff --git a/src/main/java/com/android/tools/r8/ir/code/IgnoreDebugLocalWriteAliasedValueConfiguration.java b/src/main/java/com/android/tools/r8/ir/code/IgnoreDebugLocalWriteAliasedValueConfiguration.java
new file mode 100644
index 0000000..c9dcfa2
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/code/IgnoreDebugLocalWriteAliasedValueConfiguration.java
@@ -0,0 +1,31 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.code;
+
+public class IgnoreDebugLocalWriteAliasedValueConfiguration implements AliasedValueConfiguration {
+
+  private static final IgnoreDebugLocalWriteAliasedValueConfiguration INSTANCE =
+      new IgnoreDebugLocalWriteAliasedValueConfiguration();
+
+  private IgnoreDebugLocalWriteAliasedValueConfiguration() {}
+
+  public static IgnoreDebugLocalWriteAliasedValueConfiguration getInstance() {
+    return INSTANCE;
+  }
+
+  @Override
+  public boolean isIntroducingAnAlias(Instruction instruction) {
+    return instruction.isAssume() || instruction.isDebugLocalWrite();
+  }
+
+  @Override
+  public Value getAliasForOutValue(Instruction instruction) {
+    assert instruction.isAssume() || instruction.isDebugLocalWrite();
+
+    return instruction.isAssume()
+        ? instruction.asAssume().src()
+        : instruction.asDebugLocalWrite().src();
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 4d9598e..1008d80 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -4981,7 +4981,7 @@
     }
 
     DexType instantiatedType =
-        ConstantValueUtils.getDexTypeRepresentedByValue(
+        ConstantValueUtils.getDexTypeRepresentedByValueForTracing(
             invoke.asInvokeVirtual().getReceiver(), appView);
     if (instantiatedType == null || !instantiatedType.isClassType()) {
       // Give up, we can't tell which class is being instantiated, or the type is not a class type.
@@ -5027,7 +5027,7 @@
     }
 
     DexType instantiatedType =
-        ConstantValueUtils.getDexTypeRepresentedByValue(
+        ConstantValueUtils.getDexTypeRepresentedByValueForTracing(
             constructorDefinition.getReceiver(), appView);
     if (instantiatedType == null || !instantiatedType.isClassType()) {
       // Give up, we can't tell which constructor is being invoked, or the type is not a class type.
@@ -5076,7 +5076,8 @@
           }
 
           DexType type =
-              ConstantValueUtils.getDexTypeRepresentedByValue(arrayPutInstruction.value(), appView);
+              ConstantValueUtils.getDexTypeRepresentedByValueForTracing(
+                  arrayPutInstruction.value(), appView);
           if (type == null) {
             return;
           }
@@ -5131,7 +5132,8 @@
       }
 
       ArrayPut arrayPut = user.asArrayPut();
-      DexType type = ConstantValueUtils.getDexTypeRepresentedByValue(arrayPut.value(), appView);
+      DexType type =
+          ConstantValueUtils.getDexTypeRepresentedByValueForTracing(arrayPut.value(), appView);
       if (type == null || !type.isClassType()) {
         continue;
       }
diff --git a/src/test/java/com/android/tools/r8/regress/Regress241478253.java b/src/test/java/com/android/tools/r8/regress/Regress241478253.java
index e22e8f5..ceacdf5 100644
--- a/src/test/java/com/android/tools/r8/regress/Regress241478253.java
+++ b/src/test/java/com/android/tools/r8/regress/Regress241478253.java
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.regress;
 
-import com.android.tools.r8.R8TestRunResult;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
@@ -29,22 +28,19 @@
 
   @Test
   public void testR8() throws Exception {
-    R8TestRunResult r8Release =
-        testForR8(parameters.getBackend())
-            .addProgramClasses(Foo.class, Bar.class)
-            .addKeepMainRule(Foo.class)
-            .setMinApi(parameters.getApiLevel())
-            .run(parameters.getRuntime(), Foo.class)
-            .assertSuccessWithOutputLines(EXPECTED);
-    R8TestRunResult r8Debug =
-        testForR8(parameters.getBackend())
-            .debug()
-            .addProgramClasses(Foo.class, Bar.class)
-            .addKeepMainRule(Foo.class)
-            .setMinApi(parameters.getApiLevel())
-            .run(parameters.getRuntime(), Foo.class)
-            // TODO(b/241478253): Should succeed
-            .assertFailureWithErrorThatThrows(NoSuchMethodException.class);
+    testForR8(parameters.getBackend())
+        .addProgramClasses(Foo.class, Bar.class)
+        .addKeepMainRule(Foo.class)
+        .setMinApi(parameters.getApiLevel())
+        .run(parameters.getRuntime(), Foo.class)
+        .assertSuccessWithOutputLines(EXPECTED);
+    testForR8(parameters.getBackend())
+        .debug()
+        .addProgramClasses(Foo.class, Bar.class)
+        .addKeepMainRule(Foo.class)
+        .setMinApi(parameters.getApiLevel())
+        .run(parameters.getRuntime(), Foo.class)
+        .assertSuccessWithOutputLines(EXPECTED);
   }
 
   public static class Foo {