Merge "Refactor member pool collection."
diff --git a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
index f00787b..bbb3391 100644
--- a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
@@ -12,6 +12,7 @@
 import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.Timing;
+import com.google.common.collect.Sets;
 import java.util.Map;
 import java.util.function.Function;
 
@@ -45,11 +46,15 @@
     DexType.forAllInterfaces(appInfo.dexItemFactory,
         iface -> reserveNamesInSubtypes(iface, globalState));
     timing.end();
-    // Now rename the rest.
-    timing.begin("rename");
+    // Rename the definitions.
+    timing.begin("rename-definitions");
     renameFieldsInSubtypes(appInfo.dexItemFactory.objectType);
     DexType.forAllInterfaces(appInfo.dexItemFactory, this::renameFieldsInSubtypes);
     timing.end();
+    // Rename the references that are not rebound to definitions for some reasons.
+    timing.begin("rename-references");
+    renameNonReboundReferences();
+    timing.end();
     return renaming;
   }
 
@@ -92,4 +97,44 @@
           state.assignNewNameFor(field.name, field.type, useUniqueMemberNames));
     }
   }
+
+  private void renameNonReboundReferences() {
+    // TODO(b/123068484): Collect non-rebound references instead of visiting all references.
+    Sets.union(
+        Sets.union(appInfo.staticFieldReads.keySet(), appInfo.staticFieldWrites.keySet()),
+        Sets.union(appInfo.instanceFieldReads.keySet(), appInfo.instanceFieldWrites.keySet()))
+        .forEach(this::renameNonReboundReference);
+  }
+
+  private void renameNonReboundReference(DexField field) {
+    // Already renamed
+    if (renaming.containsKey(field)) {
+      return;
+    }
+    DexEncodedField definition = appInfo.definitionFor(field);
+    if (definition != null) {
+      assert definition.field == field;
+      return;
+    }
+    // Now, `field` is reference. Find its definition and check if it's renamed.
+    DexType holderType = field.getHolder();
+    DexClass holder = appInfo.definitionFor(holderType);
+    // We don't care pruned types or library classes.
+    if (holder == null || holder.isLibraryClass()) {
+      return;
+    }
+    definition = appInfo.resolveFieldOn(holderType, field);
+    if (definition == null) {
+      // The program is already broken in the sense that it has an unresolvable field reference.
+      // Leave it as-is.
+      return;
+    }
+    assert definition.field != field;
+    assert definition.field.getHolder() != holderType;
+    // If the definition is renamed,
+    if (renaming.containsKey(definition.field)) {
+      // Assign the same, renamed name as the definition to the reference.
+      renaming.put(field, renaming.get(definition.field));
+    }
+  }
 }
diff --git a/src/test/java/com/android/tools/r8/naming/b123068484/FieldRenamingTest.java b/src/test/java/com/android/tools/r8/naming/b123068484/FieldRenamingTest.java
index d0aef41..119cb98 100644
--- a/src/test/java/com/android/tools/r8/naming/b123068484/FieldRenamingTest.java
+++ b/src/test/java/com/android/tools/r8/naming/b123068484/FieldRenamingTest.java
@@ -20,7 +20,6 @@
 import java.util.LinkedList;
 import java.util.List;
 import org.junit.BeforeClass;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -63,7 +62,6 @@
         .assertSuccessWithOutput(EXPECTED_OUTPUT);
   }
 
-  @Ignore("b/123068484")
   @Test
   public void testR8() throws Exception {
     testForR8(backend)