Desugare nest based access for invoke-special instructions in R8.

Bug: 145187969
Bug: 146124603
Change-Id: Ifba0c60a0dd03d885700e6ffa3992e9739b4d77a
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index 7ef6cd5..6233a57 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -470,6 +470,10 @@
     return true;
   }
 
+  public DexEncodedMethod getMethod() {
+    return method;
+  }
+
   public boolean isDebugMode() {
     return appView.options().debug || method.getOptimizationInfo().isReachabilitySensitive();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/NestBasedAccessDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/NestBasedAccessDesugaring.java
index ff95053..30edf6a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/NestBasedAccessDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/NestBasedAccessDesugaring.java
@@ -385,8 +385,7 @@
 
     @Override
     public boolean registerInvokeSuper(DexMethod method) {
-      // Cannot target private method.
-      return false;
+      return registerInvoke(method, Invoke.Type.SUPER);
     }
 
     @Override
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java b/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java
index 1784753..98e83c4 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/SyntheticSourceCode.java
@@ -9,11 +9,10 @@
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProto;
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.analysis.type.Nullability;
-import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
 import com.android.tools.r8.ir.code.CatchHandlers;
 import com.android.tools.r8.ir.code.Position;
 import com.android.tools.r8.ir.code.ValueType;
+import com.android.tools.r8.ir.conversion.DexSourceCode;
 import com.android.tools.r8.ir.conversion.IRBuilder;
 import com.android.tools.r8.ir.conversion.SourceCode;
 import java.util.ArrayList;
@@ -25,6 +24,7 @@
   protected final static Predicate<IRBuilder> doesNotEndBlock = x -> false;
   protected final static Predicate<IRBuilder> endsBlock = x -> true;
 
+  // TODO(b/146124603): Remove these fields as optimzations (e.g., merging) could invalidate them.
   protected final DexType receiver;
   protected final DexMethod method;
   protected final DexProto proto;
@@ -156,19 +156,11 @@
 
   @Override
   public final void buildPrelude(IRBuilder builder) {
-    if (receiver != null) {
-      builder.addThisArgument(
-          receiverRegister,
-          TypeLatticeElement.fromDexType(
-              receiver, Nullability.definitelyNotNull(), builder.appView));
-    }
-    // Fill in the Argument instructions in the argument block.
-    DexType[] parameters = proto.parameters.values;
-    for (int i = 0; i < parameters.length; i++) {
-      TypeLatticeElement typeLattice =
-          TypeLatticeElement.fromDexType(parameters[i], Nullability.maybeNull(), builder.appView);
-      builder.addNonThisArgument(paramRegisters[i], typeLattice);
-    }
+    DexSourceCode.buildArgumentsWithUnusedArgumentStubs(
+        builder,
+        0,
+        builder.getMethod(),
+        DexSourceCode::doNothingWriteConsumer);
   }
 
   @Override
diff --git a/src/test/java/com/android/tools/r8/TestRunResult.java b/src/test/java/com/android/tools/r8/TestRunResult.java
index 6170af1..e1ebfa2 100644
--- a/src/test/java/com/android/tools/r8/TestRunResult.java
+++ b/src/test/java/com/android/tools/r8/TestRunResult.java
@@ -96,7 +96,7 @@
     assertThat(
         errorMessage("Run stderr incorrect.", expectedError.getName()),
         result.stderr,
-        containsString(expectedError.getName() + ":"));
+        containsString(expectedError.getName()));
     return self();
   }
 
diff --git a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessTest.java b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessTest.java
index 9d9b8c5..a9dc70f 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialInterfaceMethodAccessTest.java
@@ -174,7 +174,7 @@
         .addProgramClasses(getClasses())
         .addProgramClassFileData(getTransformedClasses())
         .run(parameters.getRuntime(), Main.class)
-        .apply(result -> checkExpectedResult(result, false));
+        .apply(this::checkExpectedResult);
   }
 
   @Test
@@ -185,16 +185,10 @@
         .setMinApi(parameters.getApiLevel())
         .addKeepMainRule(Main.class)
         .run(parameters.getRuntime(), Main.class)
-        .apply(result -> checkExpectedResult(result, true));
+        .apply(this::checkExpectedResult);
   }
 
-  private void checkExpectedResult(TestRunResult<?> result, boolean isR8) {
-    if (isR8 && parameters.isDexRuntime() && inSameNest && symbolicReferenceIsDefiningType) {
-      // TODO(b/145187969): Incorrect nest desugaring.
-      result.assertFailureWithErrorThatThrows(VerifyError.class);
-      return;
-    }
-
+  private void checkExpectedResult(TestRunResult<?> result) {
     if (!symbolicReferenceIsDefiningType) {
       result.assertFailureWithErrorThatThrows(NoSuchMethodError.class);
       return;
diff --git a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessTest.java b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessTest.java
index 508e851..490b7dc 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessTest.java
@@ -149,7 +149,7 @@
         .addProgramClasses(getClasses())
         .addProgramClassFileData(getTransformedClasses())
         .run(parameters.getRuntime(), Main.class)
-        .apply(result -> checkExpectedResult(result, false));
+        .apply(this::checkExpectedResult);
   }
 
   @Test
@@ -160,17 +160,12 @@
         .setMinApi(parameters.getApiLevel())
         .addKeepMainRule(Main.class)
         .run(parameters.getRuntime(), Main.class)
-        .apply(result -> checkExpectedResult(result, true));
+        .apply(this::checkExpectedResult);
   }
 
-  private void checkExpectedResult(TestRunResult<?> result, boolean isR8) {
+  private void checkExpectedResult(TestRunResult<?> result) {
     if (inSameNest) {
-      if (isR8 && parameters.isDexRuntime()) {
-        // TODO(b/145187969): R8 incorrectly compiles the nest based access away.
-        result.assertFailureWithErrorThatThrows(VerifyError.class);
-      } else {
-        result.assertSuccessWithOutput(EXPECTED);
-      }
+      result.assertSuccessWithOutput(EXPECTED);
     } else {
       result.assertFailureWithErrorThatThrows(IllegalAccessError.class);
     }
diff --git a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessWithIntermediateTest.java b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessWithIntermediateTest.java
index d5f612d..52dbd4b 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessWithIntermediateTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/NestInvokeSpecialMethodAccessWithIntermediateTest.java
@@ -201,8 +201,8 @@
 
     // If in the same nest but the reference is not exact, the error is always no such method.
     if (!symbolicReferenceIsDefiningType) {
-      // TODO(b/145775365): R8/CF incorrectly compiles the input to a working program.
-      if (isR8 && parameters.isCfRuntime()) {
+      // TODO(b/145775365): R8 incorrectly compiles the input to a working program.
+      if (isR8) {
         result.assertSuccessWithOutput(EXPECTED);
         return;
       }
@@ -216,11 +216,6 @@
     }
 
     // Finally, if in the same nest and the reference is exact match the program runs successfully.
-    // TODO(b/145775365): R8/DEX incorrectly compiles the input to a non-working program.
-    if (isR8 && parameters.isDexRuntime()) {
-      result.assertFailureWithErrorThatThrows(IllegalAccessError.class);
-      return;
-    }
     result.assertSuccessWithOutput(EXPECTED);
   }
 
diff --git a/src/test/java/com/android/tools/r8/resolution/access/NestVirtualMethodAccessWithIntermediateClassTest.java b/src/test/java/com/android/tools/r8/resolution/access/NestVirtualMethodAccessWithIntermediateClassTest.java
index d6343fc..3e85f1a 100644
--- a/src/test/java/com/android/tools/r8/resolution/access/NestVirtualMethodAccessWithIntermediateClassTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/access/NestVirtualMethodAccessWithIntermediateClassTest.java
@@ -4,12 +4,8 @@
 package com.android.tools.r8.resolution.access;
 
 import static com.android.tools.r8.TestRuntime.CfVm.JDK11;
-import static org.hamcrest.core.StringContains.containsString;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
 
-import com.android.tools.r8.CompilationFailedException;
-import com.android.tools.r8.R8FullTestBuilder;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestRunResult;
@@ -89,31 +85,20 @@
 
   @Test
   public void testR8() throws Exception {
-    R8FullTestBuilder builder =
-        testForR8(parameters.getBackend())
-            .addProgramClasses(getClasses())
-            .addProgramClassFileData(getTransformedClasses())
-            .setMinApi(parameters.getApiLevel())
-            .addKeepMainRule(Main.class);
-    // TODO(b/145196085): R8 fails compilation when the classes are in the same nest.
-    if (inSameNest) {
-      if (parameters.isDexRuntime()) {
-        try {
-          builder.compile();
-        } catch (CompilationFailedException e) {
-          // Expected failure.
-          return;
-        }
-        fail("Expected failure: b/145196085");
-      }
-    }
-    builder
+    testForR8(parameters.getBackend())
+        .addProgramClasses(getClasses())
+        .addProgramClassFileData(getTransformedClasses())
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(Main.class)
         .run(parameters.getRuntime(), Main.class)
         .apply(
             result -> {
-              if (inSameNest) {
-                // TODO(b/145187969): R8 compiles out the errors when in the same nest.
+              if (inSameNest && parameters.isCfRuntime()) {
+                // TODO(b/145187969): R8/CF compiles to a "working" program.
                 result.assertSuccessWithOutput(EXPECTED);
+              } else if (inSameNest && parameters.isDexRuntime()) {
+                // TODO(b/145187969): R8/DEX compiles to a throw null program.
+                result.assertFailureWithErrorThatThrows(NullPointerException.class);
               } else {
                 checkExpectedResult(result);
               }
@@ -123,9 +108,9 @@
   private void checkExpectedResult(TestRunResult<?> result) {
     if (inSameNest && parameters.isCfRuntime()) {
       // TODO(b/145187969): Investigate if the change to NoSuchMethodError is according to spec?
-      result.assertFailureWithErrorThatMatches(containsString(NoSuchMethodError.class.getName()));
+      result.assertFailureWithErrorThatThrows(NoSuchMethodError.class);
     } else {
-      result.assertFailureWithErrorThatMatches(containsString(IllegalAccessError.class.getName()));
+      result.assertFailureWithErrorThatThrows(IllegalAccessError.class);
     }
   }