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"));
}