Take library class over program class when computing dispatch
Bug: b/234833465
Change-Id: I66e533d06b57eb5418eb25666b4cae1f8a893f75
diff --git a/src/main/java/com/android/tools/r8/graph/ClassResolutionResult.java b/src/main/java/com/android/tools/r8/graph/ClassResolutionResult.java
index 12baacf..17ba862 100644
--- a/src/main/java/com/android/tools/r8/graph/ClassResolutionResult.java
+++ b/src/main/java/com/android/tools/r8/graph/ClassResolutionResult.java
@@ -14,10 +14,12 @@
DexClass toSingleClassWithProgramOverLibrary();
+ DexClass toSingleClassWithLibraryOverProgram();
+
// The alternative class is:
// - the other class than the single class if the resolution resolves into multiple classes,
// - null if the resolution resolves into a single class.
- DexClass toAlternativeClassWithProgramOverLibrary();
+ DexClass toAlternativeClass();
void forEachClassResolutionResult(Consumer<DexClass> consumer);
@@ -95,7 +97,12 @@
}
@Override
- public DexClass toAlternativeClassWithProgramOverLibrary() {
+ public DexClass toSingleClassWithLibraryOverProgram() {
+ return null;
+ }
+
+ @Override
+ public DexClass toAlternativeClass() {
return null;
}
@@ -147,7 +154,12 @@
}
@Override
- public DexClass toAlternativeClassWithProgramOverLibrary() {
+ public DexClass toSingleClassWithLibraryOverProgram() {
+ return libraryClass;
+ }
+
+ @Override
+ public DexClass toAlternativeClass() {
return libraryClass;
}
}
@@ -166,7 +178,12 @@
}
@Override
- public DexClass toAlternativeClassWithProgramOverLibrary() {
+ public DexClass toSingleClassWithLibraryOverProgram() {
+ return libraryClass;
+ }
+
+ @Override
+ public DexClass toAlternativeClass() {
return programOrClasspathClass;
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index 717ac38d..265fc65 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -156,7 +156,12 @@
}
@Override
- public DexClass toAlternativeClassWithProgramOverLibrary() {
+ public DexClass toSingleClassWithLibraryOverProgram() {
+ return this;
+ }
+
+ @Override
+ public DexClass toAlternativeClass() {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java b/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
index 8730c35..5b43e8d 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
@@ -344,6 +344,15 @@
return null;
}
+ private static DexClass definitionForHelper(AppInfoWithClassHierarchy appInfo, DexType type) {
+ if (type == null) {
+ return null;
+ }
+ return appInfo
+ .contextIndependentDefinitionForWithResolutionResult(type)
+ .toSingleClassWithLibraryOverProgram();
+ }
+
/**
* Lookup the target of an invoke-super.
*
@@ -447,7 +456,7 @@
&& !symbolicReference.isInterface()
&& isSuperclass.test(symbolicReference, context)) {
// If reference is a super type of the context then search starts at the immediate super.
- initialType = context.superType == null ? null : appInfo.definitionFor(context.superType);
+ initialType = definitionForHelper(appInfo, context.superType);
} else {
// Otherwise it starts at the reference itself.
initialType = symbolicReference;
@@ -465,7 +474,7 @@
if (target != null) {
break;
}
- current = current.superType == null ? null : appInfo.definitionFor(current.superType);
+ current = definitionForHelper(appInfo, current.superType);
}
// 4. Otherwise, it is the single maximally specific method:
if (target == null) {
@@ -698,7 +707,7 @@
Consumer<? super DexEncodedMethod> methodCausingFailureConsumer) {
if (lambdaInstance.getMainMethod().match(resolvedMethod)) {
DexMethod methodReference = lambdaInstance.implHandle.asMethod();
- DexClass holder = appInfo.definitionForHolder(methodReference);
+ DexClass holder = definitionForHelper(appInfo, methodReference.getHolderType());
DexClassAndMethod method = methodReference.lookupMemberOnClass(holder);
if (method == null) {
// The targeted method might not exist, eg, Throwable.addSuppressed in an old library.
@@ -743,7 +752,7 @@
if (current.type == overrideTarget.getHolderType()) {
return null;
}
- current = current.superType == null ? null : appInfo.definitionFor(current.superType);
+ current = definitionForHelper(appInfo, current.superType);
continue;
}
DexClassAndMethod target = DexClassAndMethod.create(current, candidate);
@@ -817,11 +826,11 @@
}
private static DexClassAndMethod findWideningOverride(
- DexClassAndMethod resolvedMethod, DexClass clazz, AppInfoWithClassHierarchy appView) {
+ DexClassAndMethod resolvedMethod, DexClass clazz, AppInfoWithClassHierarchy appInfo) {
// Otherwise, lookup to first override that is distinct from resolvedMethod.
assert resolvedMethod.getDefinition().accessFlags.isPackagePrivate();
while (clazz.superType != null) {
- clazz = appView.definitionFor(clazz.superType);
+ clazz = definitionForHelper(appInfo, clazz.superType);
if (clazz == null) {
return resolvedMethod;
}
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 bb1e898..689a3f0 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -692,7 +692,7 @@
internalDefinitionFor(
programClass.type, programClass, this::recordNonProgramClass, this::reportMissingClass);
assert classResolutionResult.hasClassResolutionResult();
- DexClass alternativeClass = classResolutionResult.toAlternativeClassWithProgramOverLibrary();
+ DexClass alternativeClass = classResolutionResult.toAlternativeClass();
assert alternativeClass == null || alternativeClass.isLibraryClass();
return alternativeClass != null;
}
@@ -2562,9 +2562,7 @@
return;
}
DexClass alternativeResolutionResult =
- appInfo()
- .contextIndependentDefinitionForWithResolutionResult(type)
- .toAlternativeClassWithProgramOverLibrary();
+ appInfo().contextIndependentDefinitionForWithResolutionResult(type).toAlternativeClass();
if (alternativeResolutionResult != null && alternativeResolutionResult.isLibraryClass()) {
// We are in a situation where a library class inherits from a library class, which has a
// program class duplicated version for low API levels.