Retrace field definitions by class until we record residual for fields

Bug: b/280802465
Change-Id: If4aae4d390e73fe7927cc0a03dd137ba1b67a6cd
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceClassResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceClassResultImpl.java
index 98ed799..eaa21d3 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceClassResultImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceClassResultImpl.java
@@ -85,7 +85,7 @@
               memberNamings,
               memberNaming -> memberNaming.getResidualSignature().equals(fieldSignature));
     }
-    return memberNamings;
+    return memberNamings.isEmpty() ? null : memberNamings;
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetraceFieldResultImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetraceFieldResultImpl.java
index ac45d92..c7f09b8 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetraceFieldResultImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetraceFieldResultImpl.java
@@ -95,7 +95,9 @@
 
   @Override
   public boolean isEmpty() {
-    return memberNamings == null || memberNamings.isEmpty();
+    return memberNamings == null
+        || memberNamings.isEmpty()
+        || (memberNamings.size() == 1 && memberNamings.get(0).getSecond() == null);
   }
 
   public static class ElementImpl implements RetraceFieldElement {
diff --git a/src/main/java/com/android/tools/r8/utils/RetracerForCodePrinting.java b/src/main/java/com/android/tools/r8/utils/RetracerForCodePrinting.java
index fe301df..1b772b7 100644
--- a/src/main/java/com/android/tools/r8/utils/RetracerForCodePrinting.java
+++ b/src/main/java/com/android/tools/r8/utils/RetracerForCodePrinting.java
@@ -11,8 +11,10 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.IndexedDexItem;
 import com.android.tools.r8.naming.ClassNameMapper;
+import com.android.tools.r8.references.FieldReference;
 import com.android.tools.r8.retrace.RetraceClassElement;
 import com.android.tools.r8.retrace.RetraceElement;
+import com.android.tools.r8.retrace.RetraceFieldResult;
 import com.android.tools.r8.retrace.RetraceMethodResult;
 import com.android.tools.r8.retrace.RetraceResult;
 import com.android.tools.r8.retrace.RetracedFieldReference;
@@ -117,8 +119,16 @@
     if (retracer == null) {
       return noRetraceString.apply(field);
     }
+    FieldReference fieldReference = field.asFieldReference();
+    RetraceFieldResult retraceFieldResult = retracer.retraceField(fieldReference);
+    if (retraceFieldResult.isEmpty()) {
+      retraceFieldResult =
+          retracer
+              .retraceClass(fieldReference.getHolderClass())
+              .lookupField(fieldReference.getFieldName());
+    }
     return joinAmbiguousResults(
-        retracer.retraceField(field.asFieldReference()),
+        retraceFieldResult,
         element -> {
           if (element.isUnknown()) {
             return unknownToString.apply(element.getField());
diff --git a/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java b/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
index 487ac5f..262818c 100644
--- a/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
+++ b/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
@@ -193,11 +193,14 @@
             DexField originalField = appView.graphLens().getOriginalFieldSignature(dexField);
             DexField residualField =
                 appView.getNamingLens().lookupField(dexField, appView.dexItemFactory());
+            // TODO(b/280802465): We should also check for field type being changed.
             if (residualField.name != originalField.name || originalField.holder != originalType) {
               FieldSignature originalSignature =
                   FieldSignature.fromDexField(originalField, originalField.holder != originalType);
               FieldSignature residualSignature = FieldSignature.fromDexField(residualField);
               MemberNaming memberNaming = new MemberNaming(originalSignature, residualSignature);
+              // TODO(b/280802465): We should always emit the residual signature even if
+              //   the residual signature is just an alpha renaming of field type.
               if (ResidualSignatureMappingInformation.isSupported(mapFileVersion)
                   && !originalSignature.type.equals(residualSignature.type)) {
                 memberNaming.addMappingInformation(fromDexField(residualField), Unreachable::raise);