Never abort merge for computed merge groups

Change-Id: Ib009581dadc242f89933c1ad4a35e1ee7e4e8274
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index e38cfe8..6fe8388 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -2476,9 +2476,6 @@
     // specified.
     public boolean enableD8ResourcesPassThrough = false;
 
-    // TODO(b/144781417): This is disabled by default as some test apps appear to have such classes.
-    public boolean allowNonAbstractClassesWithAbstractMethods = true;
-
     public boolean verifyKeptGraphInfo = false;
 
     public boolean readInputStackMaps = true;
diff --git a/src/main/java/com/android/tools/r8/verticalclassmerging/ClassMerger.java b/src/main/java/com/android/tools/r8/verticalclassmerging/ClassMerger.java
index 45ec8e9..a198871 100644
--- a/src/main/java/com/android/tools/r8/verticalclassmerging/ClassMerger.java
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/ClassMerger.java
@@ -37,18 +37,14 @@
 import com.android.tools.r8.graph.GenericSignatureCorrectnessHelper;
 import com.android.tools.r8.graph.GenericSignaturePartialTypeArgumentApplier;
 import com.android.tools.r8.graph.MethodAccessFlags;
-import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
 import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.CollectionUtils;
 import com.android.tools.r8.utils.MethodSignatureEquivalence;
-import com.android.tools.r8.utils.ObjectUtils;
 import com.google.common.base.Equivalence;
 import com.google.common.base.Equivalence.Wrapper;
-import com.google.common.collect.Streams;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -57,9 +53,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.ExecutionException;
 import java.util.function.Predicate;
-import java.util.stream.Stream;
 
 class ClassMerger {
 
@@ -73,34 +67,33 @@
       OptimizationFeedback.getSimpleFeedback();
 
   private final AppView<AppInfoWithLiveness> appView;
-  private final VerticalClassMergerGraphLens.Builder deferredRenamings;
   private final DexItemFactory dexItemFactory;
   private final VerticalClassMergerGraphLens.Builder lensBuilder;
+  private final VerticalClassMergerGraphLens.Builder outerLensBuilder;
   private final VerticallyMergedClasses.Builder verticallyMergedClassesBuilder;
 
   private final DexProgramClass source;
   private final DexProgramClass target;
 
-  private final List<SynthesizedBridgeCode> synthesizedBridges = new ArrayList<>();
-
-  private boolean abortMerge = false;
+  private final List<SynthesizedBridgeCode> synthesizedBridges;
 
   ClassMerger(
       AppView<AppInfoWithLiveness> appView,
-      VerticalClassMergerGraphLens.Builder lensBuilder,
+      VerticalClassMergerGraphLens.Builder outerLensBuilder,
+      List<SynthesizedBridgeCode> synthesizedBridges,
       VerticallyMergedClasses.Builder verticallyMergedClassesBuilder,
-      DexProgramClass source,
-      DexProgramClass target) {
+      VerticalMergeGroup group) {
     this.appView = appView;
-    this.deferredRenamings = new VerticalClassMergerGraphLens.Builder();
     this.dexItemFactory = appView.dexItemFactory();
-    this.lensBuilder = lensBuilder;
+    this.lensBuilder = new VerticalClassMergerGraphLens.Builder();
+    this.outerLensBuilder = outerLensBuilder;
+    this.synthesizedBridges = synthesizedBridges;
     this.verticallyMergedClassesBuilder = verticallyMergedClassesBuilder;
-    this.source = source;
-    this.target = target;
+    this.source = group.getSource();
+    this.target = group.getTarget();
   }
 
-  public boolean merge() throws ExecutionException {
+  public void merge() {
     // Merge the class [clazz] into [targetClass] by adding all methods to
     // targetClass that are not currently contained.
     // Step 1: Merge methods
@@ -137,7 +130,7 @@
                     availableMethodSignatures,
                     definition.isClassInitializer() ? Rename.NEVER : Rename.IF_NEEDED);
             add(directMethods, resultingDirectMethod, MethodSignatureEquivalence.get());
-            deferredRenamings.recordMove(directMethod.getDefinition(), resultingDirectMethod);
+            lensBuilder.recordMove(directMethod.getDefinition(), resultingDirectMethod);
             blockRedirectionOfSuperCalls(resultingDirectMethod);
 
             // Private methods in the parent class may be targeted with invoke-super if the two
@@ -146,7 +139,7 @@
                 && definition.isPrivate()
                 && AccessControl.isMemberAccessible(directMethod, source, target, appView)
                     .isTrue()) {
-              deferredRenamings.mapVirtualMethodToDirectInType(
+              lensBuilder.mapVirtualMethodToDirectInType(
                   definition.getReference(), definition, target.getType());
             }
           }
@@ -159,7 +152,7 @@
           // Remove abstract/interface methods that are shadowed. The identity mapping below is
           // needed to ensure we correctly fixup the mapping in case the signature refers to
           // merged classes.
-          deferredRenamings.recordSplit(virtualMethod, shadowedBy, null, null);
+          lensBuilder.recordSplit(virtualMethod, shadowedBy, null, null);
 
           // The override now corresponds to the method in the parent, so unset its synthetic flag
           // if the method in the parent is not synthetic.
@@ -169,28 +162,16 @@
           continue;
         }
       } else {
-        if (abortMerge) {
-          // If [virtualMethod] does not resolve to a single method in [target], abort.
-          assert restoreDebuggingState(
-              Streams.concat(directMethods.values().stream(), virtualMethods.values().stream()));
-          return false;
-        }
-
         // The method is not shadowed. If it is abstract, we can simply move it to the subclass.
         // Non-abstract methods are handled below (they cannot simply be moved to the subclass as
         // a virtual method, because they might be the target of an invoke-super instruction).
         if (virtualMethod.isAbstract()) {
-          // Abort if target is non-abstract and does not override the abstract method.
-          if (!target.isAbstract()) {
-            assert appView.options().testing.allowNonAbstractClassesWithAbstractMethods;
-            abortMerge = true;
-            return false;
-          }
+          assert target.isAbstract();
           // Update the holder of [virtualMethod] using renameMethod().
           DexEncodedMethod resultingVirtualMethod =
               renameMethod(virtualMethod, availableMethodSignatures, Rename.NEVER);
           resultingVirtualMethod.setLibraryMethodOverride(virtualMethod.isLibraryMethodOverride());
-          deferredRenamings.recordMove(virtualMethod, resultingVirtualMethod);
+          lensBuilder.recordMove(virtualMethod, resultingVirtualMethod);
           add(virtualMethods, resultingVirtualMethod, MethodSignatureEquivalence.get());
           continue;
         }
@@ -259,13 +240,7 @@
                                   .getMethodInfo(virtualMethod, source)
                                   .joiner())));
 
-      deferredRenamings.recordSplit(virtualMethod, override, bridge, resultingMethod);
-    }
-
-    if (abortMerge) {
-      assert restoreDebuggingState(
-          Streams.concat(directMethods.values().stream(), virtualMethods.values().stream()));
-      return false;
+      lensBuilder.recordSplit(virtualMethod, override, bridge, resultingMethod);
     }
 
     // Rewrite generic signatures before we merge a base with a generic signature.
@@ -347,12 +322,12 @@
       target.setNestMemberAttributes(source.getNestMembersClassAttributes());
     }
     // Step 6: Record merging.
-    assert !abortMerge;
     assert GenericSignatureCorrectnessHelper.createForVerification(
             appView, GenericSignatureContextBuilder.createForSingleClass(appView, target))
         .evaluateSignaturesForClass(target)
         .isValid();
-    return true;
+    outerLensBuilder.merge(lensBuilder);
+    verticallyMergedClassesBuilder.add(source, target);
   }
 
   /**
@@ -493,31 +468,6 @@
         type -> true);
   }
 
-  private boolean restoreDebuggingState(Stream<DexEncodedMethod> toBeDiscarded) {
-    toBeDiscarded.forEach(
-        method -> {
-          assert !method.isObsolete();
-          method.setObsolete();
-        });
-    source.forEachMethod(
-        method -> {
-          if (method.isObsolete()) {
-            method.unsetObsolete();
-          }
-        });
-    assert Streams.concat(Streams.stream(source.methods()), Streams.stream(target.methods()))
-        .allMatch(method -> !method.isObsolete());
-    return true;
-  }
-
-  public VerticalClassMergerGraphLens.Builder getRenamings() {
-    return deferredRenamings;
-  }
-
-  public List<SynthesizedBridgeCode> getSynthesizedBridges() {
-    return synthesizedBridges;
-  }
-
   private void redirectSuperCallsInTarget(DexEncodedMethod oldTarget) {
     DexMethod oldTargetReference = oldTarget.getReference();
     if (source.isInterface()) {
@@ -528,8 +478,7 @@
       // rewrite any invocations on the form "invoke-super J.m()" to "invoke-direct C.m$I()",
       // if I has a supertype J. This is due to the fact that invoke-super instructions that
       // resolve to a method on an interface never hit an implementation below that interface.
-      deferredRenamings.mapVirtualMethodToDirectInType(
-          oldTargetReference, oldTarget, target.getType());
+      lensBuilder.mapVirtualMethodToDirectInType(oldTargetReference, oldTarget, target.getType());
     } else {
       // If we merge class B into class C, and class C contains an invocation super.m(), then it
       // is insufficient to rewrite "invoke-super B.m()" to "invoke-{direct,virtual} C.m$B()" (the
@@ -546,8 +495,7 @@
         boolean resolutionSucceeds =
             appView.appInfo().resolveMethodOnClass(holder, signatureInHolder).isSingleResolution();
         if (resolutionSucceeds) {
-          deferredRenamings.mapVirtualMethodToDirectInType(
-              signatureInHolder, oldTarget, target.type);
+          lensBuilder.mapVirtualMethodToDirectInType(signatureInHolder, oldTarget, target.type);
         } else {
           break;
         }
@@ -565,12 +513,11 @@
           // TODO(b/315283244): Should not rely on lens for this. Instead precompute this before
           //  merging any classes.
           boolean resolutionSucceededBeforeMerge =
-              lensBuilder.hasMappingForSignatureInContext(holder, signatureInType)
+              outerLensBuilder.hasMappingForSignatureInContext(holder, signatureInType)
                   || appView.appInfo().lookupSuperTarget(signatureInHolder, holder, appView)
                       != null;
           if (resolutionSucceededBeforeMerge) {
-            deferredRenamings.mapVirtualMethodToDirectInType(
-                signatureInType, oldTarget, target.type);
+            lensBuilder.mapVirtualMethodToDirectInType(signatureInType, oldTarget, target.type);
           }
         }
         holder =
@@ -598,7 +545,7 @@
     //   class C extends B {
     //     public void m() { super.m(); } <- invoke needs to be rewritten to invoke-direct
     //   }
-    deferredRenamings.markMethodAsMerged(method);
+    lensBuilder.markMethodAsMerged(method);
   }
 
   private DexEncodedMethod buildBridgeMethod(
@@ -645,20 +592,15 @@
 
   // Returns the method that shadows the given method, or null if method is not shadowed.
   private DexEncodedMethod findMethodInTarget(DexEncodedMethod method) {
-    SingleResolutionResult<?> resolutionResult =
-        appView.appInfo().resolveMethodOnLegacy(target, method.getReference()).asSingleResolution();
-    if (resolutionResult == null) {
-      // May happen in case of missing classes, or if multiple implementations were found.
-      abortMerge = true;
-      return null;
+    DexEncodedMethod resolvedMethod =
+        appView.appInfo().resolveMethodOnLegacy(target, method.getReference()).getResolvedMethod();
+    assert resolvedMethod != null;
+    if (resolvedMethod != method) {
+      assert resolvedMethod.isVirtualMethod() == method.isVirtualMethod();
+      return resolvedMethod;
     }
-    DexEncodedMethod actual = resolutionResult.getResolvedMethod();
-    if (ObjectUtils.notIdentical(actual, method)) {
-      assert actual.isVirtualMethod() == method.isVirtualMethod();
-      return actual;
-    }
-    // The method is not actually overridden. This means that we will move `method` to the
-    // subtype. If `method` is abstract, then so should the subtype be.
+    // The method is not actually overridden. This means that we will move `method` to the subtype.
+    // If `method` is abstract, then so should the subtype be.
     return null;
   }
 
@@ -692,7 +634,7 @@
     for (DexEncodedField field : sourceFields) {
       DexEncodedField resultingField = renameFieldIfNeeded(field, availableFieldSignatures);
       existingFieldNames.add(resultingField.getName());
-      deferredRenamings.recordMove(field, resultingField);
+      lensBuilder.recordMove(field, resultingField);
       result[i] = resultingField;
       i++;
     }
@@ -730,7 +672,7 @@
     DexEncodedMethod result =
         method.toTypeSubstitutedMethodAsInlining(newSignature, dexItemFactory);
     result.getMutableOptimizationInfo().markForceInline();
-    deferredRenamings.recordMove(method, result);
+    lensBuilder.recordMove(method, result);
     // Renamed constructors turn into ordinary private functions. They can be private, as
     // they are only references from their direct subclass, which they were merged into.
     result.getAccessFlags().unsetConstructor();
@@ -821,10 +763,6 @@
 
   private void makeStatic(DexEncodedMethod method) {
     method.getAccessFlags().setStatic();
-    if (!method.getCode().isCfCode()) {
-      // Due to member rebinding we may have inserted bridge methods with synthesized code.
-      // Currently, there is no easy way to make such code static.
-      abortMerge = true;
-    }
+    assert method.getCode().isCfCode();
   }
 }
diff --git a/src/main/java/com/android/tools/r8/verticalclassmerging/ConnectedComponentVerticalClassMerger.java b/src/main/java/com/android/tools/r8/verticalclassmerging/ConnectedComponentVerticalClassMerger.java
index ca95ef0..fdd9383 100644
--- a/src/main/java/com/android/tools/r8/verticalclassmerging/ConnectedComponentVerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/ConnectedComponentVerticalClassMerger.java
@@ -4,14 +4,12 @@
 package com.android.tools.r8.verticalclassmerging;
 
 import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.ListUtils;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Comparator;
 import java.util.List;
-import java.util.concurrent.ExecutionException;
 
 public class ConnectedComponentVerticalClassMerger {
 
@@ -38,27 +36,16 @@
     return classesToMerge.isEmpty();
   }
 
-  public VerticalClassMergerResult.Builder run() throws ExecutionException {
+  public VerticalClassMergerResult.Builder run() {
     List<VerticalMergeGroup> classesToMergeSorted =
         ListUtils.sort(classesToMerge, Comparator.comparing(group -> group.getSource().getType()));
     for (VerticalMergeGroup group : classesToMergeSorted) {
-      mergeClassIfPossible(group);
+      ClassMerger classMerger =
+          new ClassMerger(
+              appView, lensBuilder, synthesizedBridges, verticallyMergedClassesBuilder, group);
+      classMerger.merge();
     }
     return VerticalClassMergerResult.builder(
         lensBuilder, synthesizedBridges, verticallyMergedClassesBuilder);
   }
-
-  private void mergeClassIfPossible(VerticalMergeGroup group) throws ExecutionException {
-    DexProgramClass sourceClass = group.getSource();
-    DexProgramClass targetClass = group.getTarget();
-    ClassMerger merger =
-        new ClassMerger(
-            appView, lensBuilder, verticallyMergedClassesBuilder, sourceClass, targetClass);
-    if (merger.merge()) {
-      verticallyMergedClassesBuilder.add(sourceClass, targetClass);
-      // Commit the changes to the graph lens.
-      lensBuilder.merge(merger.getRenamings());
-      synthesizedBridges.addAll(merger.getSynthesizedBridges());
-    }
-  }
 }
diff --git a/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMerger.java
index 85a48f5..9b0626b 100644
--- a/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMerger.java
@@ -182,6 +182,7 @@
   }
 
   private void run(ExecutorService executorService, Timing timing) throws ExecutionException {
+    appView.appInfo().getMethodAccessInfoCollection().verifyNoNonResolving(appView);
     timing.begin("Setup");
     ImmediateProgramSubtypingInfo immediateSubtypingInfo =
         ImmediateProgramSubtypingInfo.create(appView);
diff --git a/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMergerPolicyExecutor.java b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMergerPolicyExecutor.java
index c6b3bb9..bab7656 100644
--- a/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMergerPolicyExecutor.java
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/VerticalClassMergerPolicyExecutor.java
@@ -11,6 +11,7 @@
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.Timing;
+import com.android.tools.r8.verticalclassmerging.policies.NoAbstractMethodsOnAbstractClassesPolicy;
 import com.android.tools.r8.verticalclassmerging.policies.NoAnnotationClassesPolicy;
 import com.android.tools.r8.verticalclassmerging.policies.NoClassInitializationChangesPolicy;
 import com.android.tools.r8.verticalclassmerging.policies.NoDirectlyInstantiatedClassesPolicy;
@@ -33,6 +34,7 @@
 import com.android.tools.r8.verticalclassmerging.policies.SameMainDexGroupPolicy;
 import com.android.tools.r8.verticalclassmerging.policies.SameNestPolicy;
 import com.android.tools.r8.verticalclassmerging.policies.SameStartupPartitionPolicy;
+import com.android.tools.r8.verticalclassmerging.policies.SuccessfulVirtualMethodResolutionInTargetPolicy;
 import com.android.tools.r8.verticalclassmerging.policies.VerticalClassMergerPolicy;
 import com.android.tools.r8.verticalclassmerging.policies.VerticalClassMergerPolicyWithPreprocessing;
 import java.util.ArrayList;
@@ -87,6 +89,8 @@
             new NoClassInitializationChangesPolicy(appView),
             new NoInterfacesWithInvokeSpecialToDefaultMethodIntoClassPolicy(appView),
             new NoInvokeSuperNoSuchMethodErrorsPolicy(appView),
+            new SuccessfulVirtualMethodResolutionInTargetPolicy(appView),
+            new NoAbstractMethodsOnAbstractClassesPolicy(appView),
             new NoNestedMergingPolicy());
     groups = run(groups, policies, executorService, timing);
     return new ConnectedComponentVerticalClassMerger(appView, groups);
diff --git a/src/main/java/com/android/tools/r8/verticalclassmerging/policies/NoAbstractMethodsOnAbstractClassesPolicy.java b/src/main/java/com/android/tools/r8/verticalclassmerging/policies/NoAbstractMethodsOnAbstractClassesPolicy.java
new file mode 100644
index 0000000..f6d7d4b
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/policies/NoAbstractMethodsOnAbstractClassesPolicy.java
@@ -0,0 +1,46 @@
+// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.verticalclassmerging.policies;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClassAndMethod;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.verticalclassmerging.VerticalMergeGroup;
+
+public class NoAbstractMethodsOnAbstractClassesPolicy extends VerticalClassMergerPolicy {
+
+  private final AppView<AppInfoWithLiveness> appView;
+
+  public NoAbstractMethodsOnAbstractClassesPolicy(AppView<AppInfoWithLiveness> appView) {
+    this.appView = appView;
+  }
+
+  @Override
+  public boolean canMerge(VerticalMergeGroup group) {
+    if (!group.getSource().isAbstract() || group.getTarget().isAbstract()) {
+      return true;
+    }
+    for (ProgramMethod method :
+        group.getSource().virtualProgramMethods(DexEncodedMethod::isAbstract)) {
+      DexClassAndMethod resolvedMethod =
+          appView
+              .appInfo()
+              .resolveMethodOn(group.getTarget(), method.getReference())
+              .getResolutionPair();
+      // If the method and resolved method are different, then the abstract method will be removed
+      // and references will be rewritten to the resolved method.
+      if (resolvedMethod.getDefinition() == method.getDefinition()) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @Override
+  public String getName() {
+    return "NoAbstractMethodsOnAbstractClassesPolicy";
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/verticalclassmerging/policies/SuccessfulVirtualMethodResolutionInTargetPolicy.java b/src/main/java/com/android/tools/r8/verticalclassmerging/policies/SuccessfulVirtualMethodResolutionInTargetPolicy.java
new file mode 100644
index 0000000..a3cee74
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/verticalclassmerging/policies/SuccessfulVirtualMethodResolutionInTargetPolicy.java
@@ -0,0 +1,36 @@
+// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.verticalclassmerging.policies;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.MethodResolutionResult;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.verticalclassmerging.VerticalMergeGroup;
+
+public class SuccessfulVirtualMethodResolutionInTargetPolicy extends VerticalClassMergerPolicy {
+
+  private final AppView<AppInfoWithLiveness> appView;
+
+  public SuccessfulVirtualMethodResolutionInTargetPolicy(AppView<AppInfoWithLiveness> appView) {
+    this.appView = appView;
+  }
+
+  @Override
+  public boolean canMerge(VerticalMergeGroup group) {
+    for (ProgramMethod method : group.getSource().virtualProgramMethods()) {
+      MethodResolutionResult resolutionResult =
+          appView.appInfo().resolveMethodOn(group.getTarget(), method.getReference());
+      if (!resolutionResult.isSingleResolution()) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @Override
+  public String getName() {
+    return "SuccessfulVirtualMethodResolutionInTargetPolicy";
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAbstractLeftTest.java b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAbstractLeftTest.java
index 2917464..908da85 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAbstractLeftTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAbstractLeftTest.java
@@ -74,8 +74,6 @@
         .addProgramClassFileData(transformB())
         .addKeepMainRule(Main.class)
         .setMinApi(parameters)
-        .addOptionsModification(
-            options -> options.testing.allowNonAbstractClassesWithAbstractMethods = true)
         .run(parameters.getRuntime(), Main.class)
         .assertFailureWithErrorThatMatches(containsString("AbstractMethodError"));
   }
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAbstractRightTest.java b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAbstractRightTest.java
index 6c16dfd..d5e9fe3 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAbstractRightTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacediamonds/DefaultTopAbstractRightTest.java
@@ -74,8 +74,6 @@
         .addProgramClassFileData(transformB())
         .addKeepMainRule(Main.class)
         .setMinApi(parameters)
-        .addOptionsModification(
-            options -> options.testing.allowNonAbstractClassesWithAbstractMethods = true)
         .run(parameters.getRuntime(), Main.class)
         .assertFailureWithErrorThatMatches(containsString("AbstractMethodError"));
   }