Mark types with dependent instance constructor as instantiated

Bug: 149729626, 147972078
Change-Id: Ia030c8c90715fc73ac7ab4c6201bd316725b156b
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 4d8b108..63bfcf4 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -1308,8 +1308,8 @@
       }
     }
 
-    // TODO(b/149729626): Consider marking types with a dependent instance constructor as being
-    //  instantiated.
+    rootSet.forEachDependentInstanceConstructor(
+        holder, appView, this::enqueueHolderWithDependentInstanceConstructor);
     rootSet.forEachDependentStaticMember(holder, appView, this::enqueueDependentItem);
     compatEnqueueHolderIfDependentNonStaticMember(
         holder, rootSet.getDependentKeepClassCompatRule(holder.getType()));
@@ -1366,6 +1366,13 @@
     internalEnqueueRootItem(consequent, reasons, precondition);
   }
 
+  private void enqueueHolderWithDependentInstanceConstructor(
+      DexProgramClass clazz,
+      DexEncodedMethod instanceInitializer,
+      Set<ProguardKeepRuleBase> reasons) {
+    enqueueRootItem(clazz, reasons);
+  }
+
   private void processAnnotations(DexProgramClass holder, DexDefinition annotatedItem) {
     processAnnotations(holder, annotatedItem, annotatedItem.annotations());
   }
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 7d93686..97a794a 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -1386,6 +1386,22 @@
               });
     }
 
+    public void forEachDependentInstanceConstructor(
+        DexProgramClass clazz,
+        AppView<?> appView,
+        Consumer3<DexProgramClass, DexEncodedMethod, Set<ProguardKeepRuleBase>> fn) {
+      getDependentItems(clazz)
+          .forEach(
+              (reference, reasons) -> {
+                DexDefinition definition = appView.definitionFor(reference);
+                if (definition != null
+                    && definition.isDexEncodedMethod()
+                    && definition.asDexEncodedMethod().isInstanceInitializer()) {
+                  fn.accept(clazz, definition.asDexEncodedMethod(), reasons);
+                }
+              });
+    }
+
     public void copy(DexReference original, DexReference rewritten) {
       if (noShrinking.containsKey(original)) {
         noShrinking.put(rewritten, noShrinking.get(original));
diff --git a/src/test/java/com/android/tools/r8/compatproguard/CompatKeepClassMemberNamesTestRunner.java b/src/test/java/com/android/tools/r8/compatproguard/CompatKeepClassMemberNamesTestRunner.java
index c7ffc01..412311e 100644
--- a/src/test/java/com/android/tools/r8/compatproguard/CompatKeepClassMemberNamesTestRunner.java
+++ b/src/test/java/com/android/tools/r8/compatproguard/CompatKeepClassMemberNamesTestRunner.java
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.compatproguard;
 
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.core.AllOf.allOf;
 import static org.hamcrest.core.StringContains.containsString;
 import static org.junit.Assert.assertFalse;
@@ -175,8 +177,8 @@
               assertTrue(inspector.clazz(MAIN_CLASS).isPresent());
               assertTrue(inspector.clazz(BAR_CLASS).isPresent());
               assertBarGetInstanceIsNotInlined(inspector);
-              assertFalse(inspector.clazz(BAR_CLASS).uniqueFieldWithName("i").isPresent());
-              assertFalse(inspector.clazz(BAR_CLASS).uniqueMethodWithName("<init>").isPresent());
+              assertThat(inspector.clazz(BAR_CLASS).init(), isPresent());
+              assertThat(inspector.clazz(BAR_CLASS).uniqueFieldWithName("i"), isPresent());
             });
   }
 
@@ -286,8 +288,8 @@
               assertTrue(inspector.clazz(MAIN_CLASS).isPresent());
               assertTrue(inspector.clazz(BAR_CLASS).isPresent());
               assertBarGetInstanceIsNotInlined(inspector);
-              assertFalse(inspector.clazz(BAR_CLASS).uniqueFieldWithName("i").isPresent());
-              assertFalse(inspector.clazz(BAR_CLASS).uniqueMethodWithName("<init>").isPresent());
+              assertThat(inspector.clazz(BAR_CLASS).uniqueMethodWithName("<init>"), isPresent());
+              assertThat(inspector.clazz(BAR_CLASS).uniqueFieldWithName("i"), isPresent());
             });
   }
 
diff --git a/src/test/java/com/android/tools/r8/shaking/annotations/B149729626.java b/src/test/java/com/android/tools/r8/shaking/annotations/B149729626.java
index ab3c663..e0c497c 100644
--- a/src/test/java/com/android/tools/r8/shaking/annotations/B149729626.java
+++ b/src/test/java/com/android/tools/r8/shaking/annotations/B149729626.java
@@ -45,8 +45,6 @@
             "  <init>(...);",
             "}",
             // TODO(b/149729626): Should not be required.
-            "-keep class " + Marked.class.getTypeName(),
-            // TODO(b/149729626): Should not be required.
             "-keep class " + TestClass.class.getTypeName() + " { void makeMarkerLive(); }")
         // TODO(b/149729626): Should not be required.
         .addKeepRuntimeVisibleAnnotations()
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/ConditionalKeepIfKeptTest.java b/src/test/java/com/android/tools/r8/shaking/ifrule/ConditionalKeepIfKeptTest.java
index 50443fc..790ea8d 100644
--- a/src/test/java/com/android/tools/r8/shaking/ifrule/ConditionalKeepIfKeptTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/ConditionalKeepIfKeptTest.java
@@ -8,6 +8,7 @@
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
@@ -62,9 +63,9 @@
               ClassSubject classSubject = inspector.clazz(StaticallyReferenced.class);
               assertThat(classSubject, isPresent());
               assertEquals(0, classSubject.allFields().size());
-              // TODO(b/132318799): Full mode no-marker should not keep <init>() when not specified.
-              assertEquals(useMarker ? 0 : 1, classSubject.allMethods().size());
-              assertEquals(!useMarker, classSubject.init().isPresent());
+              // TODO(b/132318799): Should not keep <init>() when not specified.
+              assertEquals(1, classSubject.allMethods().size());
+              assertTrue(classSubject.init().isPresent());
             });
   }