Merge "Use lookupMethodInAllContexts in rewriteMixedItems"
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 2b51720..dae98ad 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -1651,7 +1651,7 @@
           rewriteKeysWhileMergingValues(previous.staticFieldWrites, lense::lookupField);
       this.fieldsRead = rewriteItems(previous.fieldsRead, lense::lookupField);
       this.fieldsWritten = rewriteItems(previous.fieldsWritten, lense::lookupField);
-      this.pinnedItems = rewriteMixedItems(previous.pinnedItems, lense);
+      this.pinnedItems = rewriteMixedItemsConservatively(previous.pinnedItems, lense);
       this.virtualInvokes = rewriteMethodsConservatively(previous.virtualInvokes, lense);
       this.interfaceInvokes = rewriteMethodsConservatively(previous.interfaceInvokes, lense);
       this.superInvokes = rewriteMethodsConservatively(previous.superInvokes, lense);
@@ -1665,7 +1665,8 @@
       this.assumedValues = previous.assumedValues;
       assert assertNotModifiedByLense(previous.alwaysInline, lense);
       this.alwaysInline = previous.alwaysInline;
-      this.identifierNameStrings = rewriteMixedItems(previous.identifierNameStrings, lense);
+      this.identifierNameStrings =
+          rewriteMixedItemsConservatively(previous.identifierNameStrings, lense);
       // Switchmap classes should never be affected by renaming.
       assert assertNotModifiedByLense(
           previous.switchMaps.keySet().stream().map(this::definitionFor).filter(Objects::nonNull)
@@ -1846,7 +1847,7 @@
       return Collections.unmodifiableMap(result);
     }
 
-    private static ImmutableSet<DexItem> rewriteMixedItems(
+    private static ImmutableSet<DexItem> rewriteMixedItemsConservatively(
         Set<DexItem> original, GraphLense lense) {
       ImmutableSet.Builder<DexItem> builder = ImmutableSet.builder();
       for (DexItem item : original) {
@@ -1854,7 +1855,12 @@
         if (item instanceof DexType) {
           builder.add(lense.lookupType((DexType) item));
         } else if (item instanceof DexMethod) {
-          builder.add(lense.lookupMethod((DexMethod) item));
+          DexMethod method = (DexMethod) item;
+          if (lense.isContextFreeForMethod(method)) {
+            builder.add(lense.lookupMethod(method));
+          } else {
+            builder.addAll(lense.lookupMethodInAllContexts(method));
+          }
         } else if (item instanceof DexField) {
           builder.add(lense.lookupField((DexField) item));
         } else {
diff --git a/src/test/examples/classmerging/RewritePinnedMethodTest.java b/src/test/examples/classmerging/RewritePinnedMethodTest.java
new file mode 100644
index 0000000..3d25805
--- /dev/null
+++ b/src/test/examples/classmerging/RewritePinnedMethodTest.java
@@ -0,0 +1,41 @@
+// Copyright (c) 2018, 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 classmerging;
+
+public class RewritePinnedMethodTest {
+
+  public static void main(String[] args) {
+    C obj = new C();
+    obj.m();
+  }
+
+  // A.m is pinned by a keep rule, to prevent it from being merged into B.
+  public static class A {
+    public void m() {
+      System.out.println("In A.m");
+    }
+  }
+
+  // B is merged into C.
+  public static class B extends A {
+    @Override
+    public void m() {
+      System.out.println("In B.m");
+      super.m();
+    }
+  }
+
+  public static class C extends B {
+    @Override
+    public void m() {
+      System.out.println("In C.m");
+      // This invocation is changed from invoke-super to invoke-direct. It would be valid for this
+      // instruction to be on the form "invoke-super A.m". Therefore, the graph lense contains a
+      // mapping for "A.m" from (context: "C.m", type: SUPER) to C.m$B, where the method C.m$B is
+      // the direct method that gets created for B.m during vertical class merging.
+      super.m();
+    }
+  }
+}
diff --git a/src/test/examples/classmerging/keep-rules.txt b/src/test/examples/classmerging/keep-rules.txt
index 01e35f3..1a20ce3 100644
--- a/src/test/examples/classmerging/keep-rules.txt
+++ b/src/test/examples/classmerging/keep-rules.txt
@@ -13,6 +13,9 @@
 -keep public class classmerging.ExceptionTest {
   public static void main(...);
 }
+-keep public class classmerging.RewritePinnedMethodTest {
+  public static void main(...);
+}
 -keep public class classmerging.SimpleInterfaceAccessTest {
   public static void main(...);
 }
diff --git a/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
index 7016163..58b87c0 100644
--- a/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
@@ -289,6 +289,30 @@
             "-keep public class classmerging.pkg.SimpleInterfaceImplRetriever"));
   }
 
+  @Ignore("b/73958515")
+  @Test
+  public void testRewritePinnedMethod() throws Exception {
+    String main = "classmerging.RewritePinnedMethodTest";
+    Path[] programFiles =
+        new Path[] {
+          CF_DIR.resolve("RewritePinnedMethodTest.class"),
+          CF_DIR.resolve("RewritePinnedMethodTest$A.class"),
+          CF_DIR.resolve("RewritePinnedMethodTest$B.class"),
+          CF_DIR.resolve("RewritePinnedMethodTest$C.class")
+        };
+    Set<String> preservedClassNames =
+        ImmutableSet.of(
+            "classmerging.RewritePinnedMethodTest",
+            "classmerging.RewritePinnedMethodTest$A",
+            "classmerging.RewritePinnedMethodTest$C");
+    runTest(
+        main,
+        programFiles,
+        preservedClassNames,
+        getProguardConfig(
+            EXAMPLE_KEEP, "-keep class classmerging.RewritePinnedMethodTest$A { *; }"));
+  }
+
   @Test
   public void testTemplateMethodPattern() throws Exception {
     String main = "classmerging.TemplateMethodTest";