Use a resolved target during bottom-up propagation.

Bug: 137038659, 133208961
Change-Id: I8ad319466462e73fe684ab42b0900cd442f9e80f
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
index f59def9..f9efa44 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -319,7 +319,16 @@
     for (DexType subType : subTypes) {
       DexMethod referenceInSubType =
           appView.dexItemFactory().createMethod(subType, reference.proto, reference.name);
-      ProguardMemberRule ruleInSubType = assumeRulePool.get(referenceInSubType);
+      // Those rules are bound to definitions, not references. If the current subtype does not
+      // override the method, and when the retrieval of bound rule fails, it is unclear whether it
+      // is due to the lack of the definition or it indeed means no matching rules. Similar to how
+      // we apply those assume rules, here we use a resolved target.
+      DexEncodedMethod target =
+          appView.appInfo().resolveMethod(subType, referenceInSubType).asResultOfResolve();
+      if (target == null) {
+        continue;
+      }
+      ProguardMemberRule ruleInSubType = assumeRulePool.get(target.method);
       // We are looking for the greatest lower bound of assume rules from all sub types.
       // If any subtype doesn't have a matching assume rule, the lower bound is literally nothing.
       if (ruleInSubType == null) {
diff --git a/src/test/java/com/android/tools/r8/shaking/assumenosideeffects/AssumenosideeffectsPropagationWithoutMatchingDefinitionTest.java b/src/test/java/com/android/tools/r8/shaking/assumenosideeffects/AssumenosideeffectsPropagationWithoutMatchingDefinitionTest.java
index 871b1d8..8095379 100644
--- a/src/test/java/com/android/tools/r8/shaking/assumenosideeffects/AssumenosideeffectsPropagationWithoutMatchingDefinitionTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/assumenosideeffects/AssumenosideeffectsPropagationWithoutMatchingDefinitionTest.java
@@ -4,8 +4,9 @@
 package com.android.tools.r8.shaking.assumenosideeffects;
 
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertEquals;
 
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.NeverMerge;
@@ -45,6 +46,7 @@
   // We propagated assume* rules only if all the subtypes' corresponding methods have the same rule.
   // The lack of matching definitions in this sub type blocks us from marking methods in the super
   // type, in this example, LoggerInterface#debug(...).
+  // By using a resolved target, we will look up a rule for BaseImplementer#debug(...) instead.
 }
 
 // To bother single target resolution. In fact, not used at all.
@@ -125,8 +127,7 @@
         .noMinification()
         .setMinApi(parameters.getRuntime())
         .run(parameters.getRuntime(), MAIN)
-        // TODO(b/137038659): should be able to remove logging.
-        .assertSuccessWithOutput(JVM_OUTPUT)
+        .assertSuccessWithOutput(OUTPUT_WITHOUT_LOGGING)
         .inspect(this::inspect);
   }
 
@@ -136,14 +137,12 @@
 
     MethodSubject mainMethod = main.mainMethod();
     assertThat(mainMethod, isPresent());
-    // TODO(b/137038659): can be zero.
-    assertNotEquals(
+    assertEquals(
         0,
         Streams.stream(mainMethod.iterateInstructions(
             i -> i.isInvoke() && i.getMethod().name.toString().equals("debug"))).count());
 
     MethodSubject testInvokeInterface = main.uniqueMethodWithName("testInvokeInterface");
-    // TODO(b/137038659): can be removed entirely.
-    assertThat(testInvokeInterface, isPresent());
+    assertThat(testInvokeInterface, not(isPresent()));
   }
 }