Allow vertical class merging even when inlining is disabled

Change-Id: Ie3fbb32f62f50303c9a0e14a583514cd622662fd
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 215ced9..320180e 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -369,11 +369,11 @@
           timing.end();
         }
         appView.setGraphLense(new MemberRebindingAnalysis(appViewWithLiveness).run());
-        // Class merging requires inlining.
-        if (options.enableClassMerging && options.enableInlining) {
+        if (options.enableClassMerging) {
           timing.begin("ClassMerger");
           VerticalClassMerger classMerger =
-              new VerticalClassMerger(application, appViewWithLiveness, executorService, timing);
+              new VerticalClassMerger(
+                  application, appViewWithLiveness, executorService, options, timing);
           appView.setGraphLense(classMerger.run());
           timing.end();
           application = application.asDirect().rewrittenWithLense(appView.getGraphLense());
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index 8dec498..3e4700c 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -39,6 +39,7 @@
 import com.android.tools.r8.logging.Log;
 import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.utils.FieldSignatureEquivalence;
+import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.MethodSignatureEquivalence;
 import com.android.tools.r8.utils.Timing;
 import com.google.common.base.Equivalence;
@@ -163,6 +164,7 @@
   private final ExecutorService executorService;
   private final GraphLense graphLense;
   private final MethodPoolCollection methodPoolCollection;
+  private final InternalOptions options;
   private final Timing timing;
   private Collection<DexMethod> invokes;
 
@@ -185,12 +187,14 @@
       DexApplication application,
       AppView<AppInfoWithLiveness> appView,
       ExecutorService executorService,
+      InternalOptions options,
       Timing timing) {
     this.application = application;
     this.appInfo = appView.getAppInfo();
     this.executorService = executorService;
     this.graphLense = appView.getGraphLense();
     this.methodPoolCollection = new MethodPoolCollection(application);
+    this.options = options;
     this.renamedMembersLense = new VerticalClassMergerGraphLense.Builder();
     this.timing = timing;
 
@@ -1494,20 +1498,20 @@
   }
 
   private boolean disallowInlining(DexEncodedMethod method, DexType invocationContext) {
-    // TODO(christofferqa): Determine the situations where markForceInline() may fail, and ensure
-    // that we always return true here in these cases.
-    if (method.getCode().isJarCode()) {
-      JarCode jarCode = method.getCode().asJarCode();
-      ConstraintWithTarget constraint =
-          jarCode.computeInliningConstraint(
-              method,
-              appInfo,
-              new SingleTypeMapperGraphLense(method.method.holder, invocationContext),
-              invocationContext);
-      return constraint == ConstraintWithTarget.NEVER;
+    if (options.enableInlining) {
+      if (method.getCode().isJarCode()) {
+        JarCode jarCode = method.getCode().asJarCode();
+        ConstraintWithTarget constraint =
+            jarCode.computeInliningConstraint(
+                method,
+                appInfo,
+                new SingleTypeMapperGraphLense(method.method.holder, invocationContext),
+                invocationContext);
+        return constraint == ConstraintWithTarget.NEVER;
+      }
+      // TODO(christofferqa): For non-jar code we currently cannot guarantee that markForceInline()
+      // will succeed.
     }
-    // TODO(christofferqa): For non-jar code we currently cannot guarantee that markForceInline()
-    // will succeed.
     return true;
   }
 
diff --git a/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
index 2a56ef5..aad109a 100644
--- a/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
@@ -262,6 +262,31 @@
   }
 
   @Test
+  public void testMergeInterfaceWithoutInlining() throws Throwable {
+    String main = "classmerging.ConflictingInterfaceSignaturesTest";
+    Path[] programFiles =
+        new Path[] {
+          CF_DIR.resolve("ConflictingInterfaceSignaturesTest.class"),
+          CF_DIR.resolve("ConflictingInterfaceSignaturesTest$A.class"),
+          CF_DIR.resolve("ConflictingInterfaceSignaturesTest$B.class"),
+          CF_DIR.resolve("ConflictingInterfaceSignaturesTest$InterfaceImpl.class")
+        };
+    Set<String> preservedClassNames =
+        ImmutableSet.of(
+            "classmerging.ConflictingInterfaceSignaturesTest",
+            "classmerging.ConflictingInterfaceSignaturesTest$InterfaceImpl");
+    runTestOnInput(
+        main,
+        readProgramFiles(programFiles),
+        preservedClassNames::contains,
+        getProguardConfig(EXAMPLE_KEEP),
+        options -> {
+          this.configure(options);
+          options.enableInlining = false;
+        });
+  }
+
+  @Test
   public void testMethodCollision() throws Throwable {
     String main = "classmerging.MethodCollisionTest";
     Path[] programFiles =