Version 1.4.72

Cherry pick: Process annotations on live fields
CL: https://r8-review.googlesource.com/c/r8/+/35721

Cherry pick: Fix typo in AnnotationsOfFieldsTest
CL: https://r8-review.googlesource.com/c/r8/+/35780

Cherry pick: Ensure app services are always available to Enqueuer
CL: https://r8-review.googlesource.com/c/r8/+/35742

Cherry pick: Set AppServices info in tests before using Enqueuer
CL: https://r8-review.googlesource.com/c/r8/+/35782

Bug: 126597509, 128387933
Change-Id: I6c737e00318dd6d0cee4c2c2a3f2f507aab3df41
diff --git a/src/main/java/com/android/tools/r8/GenerateMainDexList.java b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
index aafe941..da47fe2 100644
--- a/src/main/java/com/android/tools/r8/GenerateMainDexList.java
+++ b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppServices;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexReference;
@@ -47,6 +48,8 @@
       AppView<? extends AppInfoWithSubtyping> appView =
           new AppView<>(
               new AppInfoWithSubtyping(application), GraphLense.getIdentityLense(), options);
+      appView.setAppServices(AppServices.builder(appView).build());
+
       RootSet mainDexRootSet =
           new RootSetBuilder(appView, application, options.mainDexKeepRules, options).run(executor);
 
diff --git a/src/main/java/com/android/tools/r8/PrintSeeds.java b/src/main/java/com/android/tools/r8/PrintSeeds.java
index 475ca70..060045a 100644
--- a/src/main/java/com/android/tools/r8/PrintSeeds.java
+++ b/src/main/java/com/android/tools/r8/PrintSeeds.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppServices;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.GraphLense;
@@ -86,6 +87,7 @@
       AppView<? extends AppInfoWithSubtyping> appView =
           new AppView<>(
               new AppInfoWithSubtyping(application), GraphLense.getIdentityLense(), options);
+      appView.setAppServices(AppServices.builder(appView).build());
       RootSet rootSet =
           new RootSetBuilder(
                   appView, application, options.getProguardConfiguration().getRules(), options)
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 2f7ec60..574be8d 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
 
   // This field is accessed from release scripts using simple pattern matching.
   // Therefore, changing this field could break our release scripts.
-  public static final String LABEL = "1.4.71";
+  public static final String LABEL = "1.4.72";
 
   private Version() {
   }
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 2412662..37a83bf 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -307,6 +307,7 @@
       GraphConsumer keptGraphConsumer,
       boolean forceProguardCompatibility,
       ProguardConfiguration.Builder compatibility) {
+    assert appView.appServices() != null;
     this.appInfo = appView.appInfo();
     this.appView = appView;
     this.compatibility = compatibility;
@@ -1146,6 +1147,7 @@
             encodedField.field);
       }
     }
+    processAnnotations(encodedField, encodedField.annotations.annotations);
     liveFields.add(encodedField, reason);
     collectProguardCompatibilityRule(reason);
     // Add all dependent members to the workqueue.
@@ -1159,6 +1161,7 @@
     if (Log.ENABLED) {
       Log.verbose(getClass(), "Adding instance field `%s` to live set.", field.field);
     }
+    processAnnotations(field, field.annotations.annotations);
     liveFields.add(field, reason);
     collectProguardCompatibilityRule(reason);
     // Add all dependent members to the workqueue.
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java b/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java
index 58c4237..1ae55a5 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/NonNullTrackerTestBase.java
@@ -7,6 +7,7 @@
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppServices;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.GraphLense;
@@ -34,6 +35,7 @@
     AppView<AppInfoWithSubtyping> appView =
         new AppView<>(
             new AppInfoWithSubtyping(dexApplication), GraphLense.getIdentityLense(), TEST_OPTIONS);
+    appView.setAppServices(AppServices.builder(appView).build());
     ExecutorService executorService = ThreadUtils.getExecutorService(TEST_OPTIONS);
     RootSet rootSet =
         new RootSetBuilder(
diff --git a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
index 4dcb52f..642864f 100644
--- a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
+++ b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
@@ -5,12 +5,12 @@
 
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppServices;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.shaking.Enqueuer;
-import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.shaking.ProguardConfiguration;
 import com.android.tools.r8.shaking.RootSetBuilder;
 import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
@@ -71,17 +71,15 @@
 
     AppView<AppInfoWithSubtyping> appView =
         new AppView<>(new AppInfoWithSubtyping(program), GraphLense.getIdentityLense(), options);
+    appView.setAppServices(AppServices.builder(appView).build());
+
     RootSet rootSet =
         new RootSetBuilder(appView, program, configuration.getRules(), options).run(executor);
 
     Enqueuer enqueuer = new Enqueuer(appView, options, null, options.forceProguardCompatibility);
-    AppInfoWithLiveness appInfo =
-        enqueuer.traceApplication(rootSet, configuration.getDontWarnPatterns(), executor, timing);
-    return new Minifier(
-        new AppView<>(appInfo, GraphLense.getIdentityLense(), options),
-        rootSet,
-        Collections.emptySet())
-        .run(timing);
+    appView.setAppInfo(
+        enqueuer.traceApplication(rootSet, configuration.getDontWarnPatterns(), executor, timing));
+    return new Minifier(appView.withLiveness(), rootSet, Collections.emptySet()).run(timing);
   }
 
   static <T> Collection<Object[]> createTests(List<String> tests, Map<String, T> inspections) {
diff --git a/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java b/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
index 7ec1613..7f1ec89 100644
--- a/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.AsmTestBase;
 import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppServices;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
 import com.android.tools.r8.graph.DexEncodedMethod;
@@ -107,7 +108,7 @@
     AppView<? extends AppInfoWithSubtyping> appView =
         new AppView<>(
             new AppInfoWithSubtyping(application), GraphLense.getIdentityLense(), options);
-
+    appView.setAppServices(AppServices.builder(appView).build());
     ExecutorService executor = Executors.newSingleThreadExecutor();
     RootSet rootSet =
         new RootSetBuilder(
diff --git a/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnFieldsTest.java b/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnFieldsTest.java
new file mode 100644
index 0000000..03ace58
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/annotations/AnnotationsOnFieldsTest.java
@@ -0,0 +1,106 @@
+package com.android.tools.r8.shaking.annotations;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static org.junit.Assert.assertThat;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.FieldSubject;
+import com.google.common.collect.ImmutableList;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class AnnotationsOnFieldsTest extends TestBase {
+
+  private final Backend backend;
+
+  @Parameterized.Parameters(name = "Backend: {0}")
+  public static Backend[] data() {
+    return Backend.values();
+  }
+
+  public AnnotationsOnFieldsTest(Backend backend) {
+    this.backend = backend;
+  }
+
+  List<Class<?>> CLASSES =
+      ImmutableList.of(
+          FieldAnnotation.class,
+          StaticFieldAnnotation.class,
+          FieldAnnotationUse.class,
+          StaticFieldAnnotationUse.class,
+          TestClass.class,
+          MainClass.class);
+
+  @Test
+  public void test() throws Exception {
+    testForR8Compat(backend)
+        .enableClassInliningAnnotations()
+        .addProgramClasses(CLASSES)
+        .addKeepMainRule(MainClass.class)
+        .addKeepRules("-keep @interface **.*Annotation { *; }")
+        .addKeepRules("-keepclassmembers class * { @**.*Annotation <fields>; }")
+        .addKeepRules("-keepattributes *Annotation*")
+        .compile()
+        .inspect(
+            inspector -> {
+              ClassSubject clazz = inspector.clazz(TestClass.class);
+              assertThat(clazz, isRenamed());
+
+              FieldSubject field = clazz.uniqueFieldWithName("field");
+              assertThat(field, isPresent());
+              assertThat(field.annotation(FieldAnnotation.class.getTypeName()), isPresent());
+              assertThat(inspector.clazz(FieldAnnotationUse.class), isRenamed());
+
+              FieldSubject staticField = clazz.uniqueFieldWithName("staticField");
+              assertThat(staticField, isPresent());
+              assertThat(
+                  staticField.annotation(StaticFieldAnnotation.class.getTypeName()), isPresent());
+              assertThat(inspector.clazz(StaticFieldAnnotationUse.class), isRenamed());
+            })
+        .run(MainClass.class)
+        .assertSuccess();
+  }
+}
+
+@Target(FIELD)
+@Retention(RUNTIME)
+@interface FieldAnnotation {
+  Class<?> clazz();
+}
+
+@Target(FIELD)
+@Retention(RUNTIME)
+@interface StaticFieldAnnotation {
+  Class<?> clazz();
+}
+
+class FieldAnnotationUse {}
+
+class StaticFieldAnnotationUse {}
+
+@NeverClassInline
+class TestClass {
+
+  @StaticFieldAnnotation(clazz = StaticFieldAnnotationUse.class)
+  static int staticField;
+
+  @FieldAnnotation(clazz = FieldAnnotationUse.class)
+  int field;
+}
+
+class MainClass {
+
+  public static void main(String[] args) {
+    new TestClass();
+  }
+}