Reland "Refactor building of signature contexts to prepare for validation"
This reverts commit 980c2cdb0b487bd41f0cd40b611bdf8919264a9e.
Reason for revert: Not failing
Change-Id: Iae3ca495d924cc329372624e541adf7879324473
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 581d808..782a737 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -33,7 +33,8 @@
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DirectMappedDexApplication;
-import com.android.tools.r8.graph.GenericSignatureTypeVariableRemover;
+import com.android.tools.r8.graph.GenericSignatureContextBuilder;
+import com.android.tools.r8.graph.GenericSignatureCorrectnessHelper;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.PrunedItems;
@@ -376,9 +377,14 @@
appView.withGeneratedExtensionRegistryShrinker(
shrinker -> shrinker.run(Mode.INITIAL_TREE_SHAKING));
- // Build enclosing information and type-paramter information before pruning.
- GenericSignatureTypeVariableRemover typeVariableRemover =
- GenericSignatureTypeVariableRemover.create(appView, appView.appInfo().classes());
+ // Build enclosing information and type-parameter information before pruning.
+ // TODO(b/187922482): Only consider referenced classes.
+ GenericSignatureContextBuilder genericContextBuilder =
+ GenericSignatureContextBuilder.create(appView.appInfo().classes());
+
+ // Compute if all signatures are valid before modifying them.
+ GenericSignatureCorrectnessHelper.createForInitialCheck(appView, genericContextBuilder)
+ .run(appView.appInfo().classes());
TreePruner pruner = new TreePruner(appViewWithLiveness);
DirectMappedDexApplication prunedApp = pruner.run(executorService);
@@ -403,8 +409,7 @@
annotationRemoverBuilder
.build(appViewWithLiveness, removedClasses);
annotationRemover.ensureValid().run();
- typeVariableRemover.removeDeadGenericSignatureTypeVariables(appView);
- new GenericSignatureRewriter(appView, NamingLens.getIdentityLens())
+ new GenericSignatureRewriter(appView, NamingLens.getIdentityLens(), genericContextBuilder)
.run(appView.appInfo().classes(), executorService);
}
} finally {
@@ -596,8 +601,8 @@
shrinker -> shrinker.run(enqueuer.getMode()),
DefaultTreePrunerConfiguration.getInstance());
- GenericSignatureTypeVariableRemover typeVariableRemover =
- GenericSignatureTypeVariableRemover.create(appView, appView.appInfo().classes());
+ GenericSignatureContextBuilder genericContextBuilder =
+ GenericSignatureContextBuilder.create(appView.appInfo().classes());
TreePruner pruner = new TreePruner(appViewWithLiveness, treePrunerConfiguration);
DirectMappedDexApplication application = pruner.run(executorService);
@@ -638,7 +643,10 @@
AnnotationRemover.builder()
.build(appView.withLiveness(), removedClasses)
.run();
- typeVariableRemover.removeDeadGenericSignatureTypeVariables(appView);
+ new GenericSignatureRewriter(
+ appView, NamingLens.getIdentityLens(), genericContextBuilder)
+ .run(appView.appInfo().classes(), executorService);
+
// Synthesize fields for triggering class initializers.
new ClassInitFieldSynthesizer(appViewWithLiveness).run(executorService);
}
@@ -786,6 +794,16 @@
options.syntheticProguardRulesConsumer.accept(synthesizedProguardRules);
}
+ assert appView.checkForTesting(
+ () ->
+ !options.isShrinking()
+ || GenericSignatureCorrectnessHelper.createForVerification(
+ appView,
+ GenericSignatureContextBuilder.create(appView.appInfo().classes()))
+ .run(appView.appInfo().classes())
+ .isValid())
+ : "Could not validate generic signatures";
+
NamingLens prefixRewritingNamingLens =
PrefixRewritingNamingLens.createPrefixRewritingNamingLens(appView, namingLens);
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 04cf5cc..860adf1 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -1318,6 +1318,7 @@
!isAbstract(),
builder ->
builder
+ .setGenericSignature(MethodTypeSignature.noSignature())
.setCode(
ForwardMethodBuilder.builder(definitions.dexItemFactory())
.setStaticSource(newMethod)
@@ -1379,7 +1380,8 @@
builder(this)
.promoteToStatic()
.withoutThisParameter()
- .adjustOptimizationInfoAfterRemovingThisParameter();
+ .adjustOptimizationInfoAfterRemovingThisParameter()
+ .setGenericSignature(MethodTypeSignature.noSignature());
DexEncodedMethod method = builder.build();
method.copyMetadata(this);
setObsolete();
@@ -1510,7 +1512,7 @@
private DexMethod method;
private MethodAccessFlags accessFlags;
- private final MethodTypeSignature genericSignature;
+ private MethodTypeSignature genericSignature;
private final DexAnnotationSet annotations;
private OptionalBool isLibraryMethodOverride = OptionalBool.UNKNOWN;
private ParameterAnnotationsList parameterAnnotations;
@@ -1710,5 +1712,10 @@
buildConsumer.accept(result);
return result;
}
+
+ public Builder setGenericSignature(MethodTypeSignature methodSignature) {
+ this.genericSignature = methodSignature;
+ return this;
+ }
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/EnclosingMethodAttribute.java b/src/main/java/com/android/tools/r8/graph/EnclosingMethodAttribute.java
index fde5f6c..d2ea75e 100644
--- a/src/main/java/com/android/tools/r8/graph/EnclosingMethodAttribute.java
+++ b/src/main/java/com/android/tools/r8/graph/EnclosingMethodAttribute.java
@@ -52,6 +52,10 @@
return enclosingMethod != null;
}
+ public boolean hasEnclosingClass() {
+ return enclosingClass != null;
+ }
+
public DexMethod getEnclosingMethod() {
return enclosingMethod;
}
diff --git a/src/main/java/com/android/tools/r8/graph/GenericSignature.java b/src/main/java/com/android/tools/r8/graph/GenericSignature.java
index 9a34638..419125d 100644
--- a/src/main/java/com/android/tools/r8/graph/GenericSignature.java
+++ b/src/main/java/com/android/tools/r8/graph/GenericSignature.java
@@ -173,6 +173,7 @@
this.name = name;
this.classBound = classBound;
this.interfaceBounds = interfaceBounds;
+ assert classBound != null;
assert interfaceBounds != null;
}
@@ -189,14 +190,16 @@
}
public FormalTypeParameter visit(GenericSignatureVisitor visitor) {
- FieldTypeSignature rewrittenClassBound =
- classBound == null ? null : visitor.visitClassBound(classBound);
+ FieldTypeSignature rewrittenClassBound = visitor.visitClassBound(classBound);
List<FieldTypeSignature> rewrittenInterfaceBounds =
visitor.visitInterfaceBounds(interfaceBounds);
if (classBound == rewrittenClassBound && interfaceBounds == rewrittenInterfaceBounds) {
return this;
}
- return new FormalTypeParameter(name, rewrittenClassBound, rewrittenInterfaceBounds);
+ return new FormalTypeParameter(
+ name,
+ rewrittenClassBound == null ? FieldTypeSignature.noSignature() : rewrittenClassBound,
+ rewrittenInterfaceBounds);
}
}
@@ -286,6 +289,10 @@
public static ClassSignature noSignature() {
return NO_CLASS_SIGNATURE;
}
+
+ public ClassSignature toObjectBoundWithSameFormals(ClassTypeSignature objectBound) {
+ return new ClassSignature(formalTypeParameters, objectBound, getEmptySuperInterfaces());
+ }
}
private static class InvalidClassSignature extends ClassSignature {
@@ -649,7 +656,7 @@
if (elementSignature == rewrittenElementSignature) {
return this;
}
- return new ArrayTypeSignature(elementSignature, getWildcardIndicator());
+ return new ArrayTypeSignature(rewrittenElementSignature, getWildcardIndicator());
}
}
@@ -891,7 +898,7 @@
return parser.parseClassSignature(signature);
} catch (GenericSignatureFormatError e) {
diagnosticsHandler.warning(
- GenericSignatureDiagnostic.invalidClassSignature(signature, className, origin, e));
+ GenericSignatureFormatDiagnostic.invalidClassSignature(signature, className, origin, e));
return ClassSignature.NO_CLASS_SIGNATURE;
}
}
@@ -910,7 +917,7 @@
return parser.parseFieldTypeSignature(signature);
} catch (GenericSignatureFormatError e) {
diagnosticsHandler.warning(
- GenericSignatureDiagnostic.invalidFieldSignature(signature, fieldName, origin, e));
+ GenericSignatureFormatDiagnostic.invalidFieldSignature(signature, fieldName, origin, e));
return GenericSignature.NO_FIELD_TYPE_SIGNATURE;
}
}
@@ -929,7 +936,8 @@
return parser.parseMethodTypeSignature(signature);
} catch (GenericSignatureFormatError e) {
diagnosticsHandler.warning(
- GenericSignatureDiagnostic.invalidMethodSignature(signature, methodName, origin, e));
+ GenericSignatureFormatDiagnostic.invalidMethodSignature(
+ signature, methodName, origin, e));
return MethodTypeSignature.NO_METHOD_TYPE_SIGNATURE;
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/GenericSignatureTypeVariableRemover.java b/src/main/java/com/android/tools/r8/graph/GenericSignatureContextBuilder.java
similarity index 65%
rename from src/main/java/com/android/tools/r8/graph/GenericSignatureTypeVariableRemover.java
rename to src/main/java/com/android/tools/r8/graph/GenericSignatureContextBuilder.java
index 7c0ee29..1a05232 100644
--- a/src/main/java/com/android/tools/r8/graph/GenericSignatureTypeVariableRemover.java
+++ b/src/main/java/com/android/tools/r8/graph/GenericSignatureContextBuilder.java
@@ -4,11 +4,11 @@
package com.android.tools.r8.graph;
-import static com.android.tools.r8.graph.GenericSignatureTypeVariableRemover.TypeParameterContext.empty;
-import static com.google.common.base.Predicates.alwaysFalse;
+import static com.android.tools.r8.graph.GenericSignatureContextBuilder.TypeParameterContext.empty;
import com.android.tools.r8.graph.GenericSignature.FormalTypeParameter;
import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -18,9 +18,8 @@
import java.util.Set;
import java.util.function.Predicate;
-public class GenericSignatureTypeVariableRemover {
+public class GenericSignatureContextBuilder {
- private final DexType objectType;
private final Map<DexReference, TypeParameterSubstitutions> formalsInfo;
private final Map<DexReference, DexReference> enclosingInfo;
@@ -51,7 +50,7 @@
}
}
- static class TypeParameterContext {
+ public static class TypeParameterContext {
private static final TypeParameterContext EMPTY =
new TypeParameterContext(Collections.emptyMap(), Collections.emptySet());
@@ -69,37 +68,99 @@
if (information == null) {
return this;
}
- HashMap<String, DexType> newPruned = new HashMap<>(prunedParametersWithBounds);
- HashSet<String> newLiveParameters = new HashSet<>(liveParameters);
- information.parametersWithBounds.forEach(
- (param, type) -> {
- if (dead) {
- newPruned.put(param, type);
- newLiveParameters.remove(param);
- } else {
- newLiveParameters.add(param);
- newPruned.remove(param);
- }
- });
- return new TypeParameterContext(newPruned, newLiveParameters);
+ return dead
+ ? addPrunedSubstitutions(information.parametersWithBounds)
+ : addLiveParameters(information.parametersWithBounds.keySet());
}
public static TypeParameterContext empty() {
return EMPTY;
}
+
+ public boolean isLiveParameter(String parameterName) {
+ return liveParameters.contains(parameterName);
+ }
+
+ public DexType getPrunedSubstitution(String parameterName) {
+ assert !isLiveParameter(parameterName);
+ return prunedParametersWithBounds.get(parameterName);
+ }
+
+ public TypeParameterContext addLiveParameters(Collection<String> typeParameters) {
+ if (typeParameters.isEmpty()) {
+ return this;
+ }
+ HashSet<String> newLiveParameters = new HashSet<>();
+ newLiveParameters.addAll(liveParameters);
+ newLiveParameters.addAll(typeParameters);
+ HashMap<String, DexType> newPruned = new HashMap<>();
+ prunedParametersWithBounds.forEach(
+ (name, type) -> {
+ if (!typeParameters.contains(name)) {
+ newPruned.put(name, type);
+ }
+ });
+ return new TypeParameterContext(newPruned, newLiveParameters);
+ }
+
+ public TypeParameterContext addPrunedSubstitutions(Map<String, DexType> substitutions) {
+ if (substitutions.isEmpty()) {
+ return this;
+ }
+ HashMap<String, DexType> newPruned = new HashMap<>();
+ newPruned.putAll(prunedParametersWithBounds);
+ newPruned.putAll(substitutions);
+ HashSet<String> newLiveParameters = new HashSet<>();
+ liveParameters.forEach(
+ name -> {
+ if (!substitutions.containsKey(name)) {
+ newLiveParameters.add(name);
+ }
+ });
+ return new TypeParameterContext(newPruned, newLiveParameters);
+ }
}
- private GenericSignatureTypeVariableRemover(
+ public static class AlwaysLiveTypeParameterContext extends TypeParameterContext {
+
+ private AlwaysLiveTypeParameterContext() {
+ super(Collections.emptyMap(), Collections.emptySet());
+ }
+
+ public static AlwaysLiveTypeParameterContext create() {
+ return new AlwaysLiveTypeParameterContext();
+ }
+
+ @Override
+ public boolean isLiveParameter(String parameterName) {
+ return true;
+ }
+
+ @Override
+ public DexType getPrunedSubstitution(String parameterName) {
+ assert false;
+ return null;
+ }
+
+ @Override
+ public TypeParameterContext addLiveParameters(Collection<String> typeParameters) {
+ return this;
+ }
+
+ @Override
+ public TypeParameterContext addPrunedSubstitutions(Map<String, DexType> substitutions) {
+ return this;
+ }
+ }
+
+ private GenericSignatureContextBuilder(
Map<DexReference, TypeParameterSubstitutions> formalsInfo,
- Map<DexReference, DexReference> enclosingInfo,
- DexType objectType) {
+ Map<DexReference, DexReference> enclosingInfo) {
this.formalsInfo = formalsInfo;
this.enclosingInfo = enclosingInfo;
- this.objectType = objectType;
}
- public static GenericSignatureTypeVariableRemover create(
- AppView<?> appView, List<DexProgramClass> programClasses) {
+ public static GenericSignatureContextBuilder create(List<DexProgramClass> programClasses) {
Map<DexReference, TypeParameterSubstitutions> formalsInfo = new IdentityHashMap<>();
Map<DexReference, DexReference> enclosingInfo = new IdentityHashMap<>();
programClasses.forEach(
@@ -137,8 +198,13 @@
: enclosingMethodAttribute.getEnclosingClass());
}
});
- return new GenericSignatureTypeVariableRemover(
- formalsInfo, enclosingInfo, appView.dexItemFactory().objectType);
+ return new GenericSignatureContextBuilder(formalsInfo, enclosingInfo);
+ }
+
+ public TypeParameterContext computeTypeParameterContext(
+ AppView<?> appView, DexReference reference, Predicate<DexType> wasPruned) {
+ assert !wasPruned.test(reference.getContextType());
+ return computeTypeParameterContext(appView, reference, wasPruned, false);
}
private TypeParameterContext computeTypeParameterContext(
@@ -175,7 +241,7 @@
return typeParameterContext.combine(formalsInfo.get(reference), prunedHere);
}
- private static boolean hasPrunedRelationship(
+ public boolean hasPrunedRelationship(
AppView<?> appView,
DexReference enclosingReference,
DexType enclosedClassType,
@@ -189,8 +255,17 @@
if (wasPruned.test(enclosingReference.getContextType()) || wasPruned.test(enclosedClassType)) {
return true;
}
- DexClass enclosingClass = appView.definitionFor(enclosingReference.getContextType());
- DexClass enclosedClass = appView.definitionFor(enclosedClassType);
+ // TODO(b/187035453): We should visit generic signatures in the enqueuer.
+ DexClass enclosingClass =
+ appView
+ .appInfo()
+ .definitionForWithoutExistenceAssert(
+ appView.graphLens().lookupClassType(enclosingReference.getContextType()));
+ DexClass enclosedClass =
+ appView
+ .appInfo()
+ .definitionForWithoutExistenceAssert(
+ appView.graphLens().lookupClassType(enclosedClassType));
if (enclosingClass == null || enclosedClass == null) {
return true;
}
@@ -207,68 +282,15 @@
}
}
- private static boolean hasGenericTypeVariables(
+ public boolean hasGenericTypeVariables(
AppView<?> appView, DexType type, Predicate<DexType> wasPruned) {
if (wasPruned.test(type)) {
return false;
}
- DexClass clazz = appView.definitionFor(type);
+ DexClass clazz = appView.definitionFor(appView.graphLens().lookupClassType(type));
if (clazz == null || clazz.isNotProgramClass() || clazz.getClassSignature().isInvalid()) {
return true;
}
return !clazz.getClassSignature().getFormalTypeParameters().isEmpty();
}
-
- public void removeDeadGenericSignatureTypeVariables(AppView<?> appView) {
- Predicate<DexType> wasPruned =
- appView.hasLiveness() ? appView.withLiveness().appInfo()::wasPruned : alwaysFalse();
- GenericSignaturePartialTypeArgumentApplier baseArgumentApplier =
- GenericSignaturePartialTypeArgumentApplier.build(
- objectType,
- (enclosing, enclosed) -> hasPrunedRelationship(appView, enclosing, enclosed, wasPruned),
- type -> hasGenericTypeVariables(appView, type, wasPruned));
- appView
- .appInfo()
- .classes()
- .forEach(
- clazz -> {
- if (clazz.getClassSignature().isInvalid()) {
- return;
- }
- TypeParameterContext computedClassFormals =
- computeTypeParameterContext(appView, clazz.getType(), wasPruned, false);
- GenericSignaturePartialTypeArgumentApplier classArgumentApplier =
- baseArgumentApplier.addSubstitutionsAndVariables(
- computedClassFormals.prunedParametersWithBounds,
- computedClassFormals.liveParameters);
- clazz.setClassSignature(
- classArgumentApplier.visitClassSignature(clazz.getClassSignature()));
- clazz
- .methods()
- .forEach(
- method -> {
- MethodTypeSignature methodSignature = method.getGenericSignature();
- if (methodSignature.hasSignature()
- && method.getGenericSignature().isValid()) {
- // The reflection api do not distinguish static methods context from
- // virtual methods.
- method.setGenericSignature(
- classArgumentApplier
- .buildForMethod(methodSignature.getFormalTypeParameters())
- .visitMethodSignature(methodSignature));
- }
- });
- clazz
- .instanceFields()
- .forEach(
- field -> {
- if (field.getGenericSignature().hasSignature()
- && field.getGenericSignature().isValid()) {
- field.setGenericSignature(
- classArgumentApplier.visitFieldTypeSignature(
- field.getGenericSignature()));
- }
- });
- });
- }
}
diff --git a/src/main/java/com/android/tools/r8/graph/GenericSignatureCorrectnessHelper.java b/src/main/java/com/android/tools/r8/graph/GenericSignatureCorrectnessHelper.java
index 3401560..7dcfb37 100644
--- a/src/main/java/com/android/tools/r8/graph/GenericSignatureCorrectnessHelper.java
+++ b/src/main/java/com/android/tools/r8/graph/GenericSignatureCorrectnessHelper.java
@@ -9,7 +9,9 @@
import static com.android.tools.r8.graph.GenericSignatureCorrectnessHelper.SignatureEvaluationResult.INVALID_SUPER_TYPE;
import static com.android.tools.r8.graph.GenericSignatureCorrectnessHelper.SignatureEvaluationResult.INVALID_TYPE_VARIABLE_UNDEFINED;
import static com.android.tools.r8.graph.GenericSignatureCorrectnessHelper.SignatureEvaluationResult.VALID;
+import static com.google.common.base.Predicates.alwaysFalse;
+import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.GenericSignature.ClassSignature;
import com.android.tools.r8.graph.GenericSignature.ClassTypeSignature;
import com.android.tools.r8.graph.GenericSignature.DexDefinitionSignature;
@@ -18,9 +20,9 @@
import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
import com.android.tools.r8.graph.GenericSignature.ReturnType;
import com.android.tools.r8.graph.GenericSignature.TypeSignature;
-import java.util.HashSet;
+import com.android.tools.r8.graph.GenericSignatureContextBuilder.TypeParameterContext;
+import com.android.tools.r8.utils.ListUtils;
import java.util.List;
-import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -29,90 +31,163 @@
private enum Mode {
VERIFY,
- MARK_AS_INVALID;
+ CLEAR_IF_INVALID;
public boolean doNotVerify() {
- return markAsInvalid();
+ return clearIfInvalid();
}
- public boolean markAsInvalid() {
- return this == MARK_AS_INVALID;
+ public boolean clearIfInvalid() {
+ return this == CLEAR_IF_INVALID;
}
}
public enum SignatureEvaluationResult {
INVALID_SUPER_TYPE,
+ INVALID_INTERFACE_TYPE,
INVALID_INTERFACE_COUNT,
INVALID_APPLICATION_COUNT,
INVALID_TYPE_VARIABLE_UNDEFINED,
VALID;
- boolean isValid() {
+ public boolean isValid() {
return this == VALID;
}
- boolean isInvalid() {
+ public boolean isInvalid() {
return this != VALID;
}
+
+ public SignatureEvaluationResult combine(SignatureEvaluationResult other) {
+ return isInvalid() ? this : other;
+ }
+
+ public String getDescription() {
+ switch (this) {
+ case INVALID_APPLICATION_COUNT:
+ return "The applied generic arguments have different count than the expected formals";
+ case INVALID_INTERFACE_COUNT:
+ return "The generic signature has a different number of interfaces than the class";
+ case INVALID_SUPER_TYPE:
+ return "The generic super type is not the same as the class super type";
+ case INVALID_TYPE_VARIABLE_UNDEFINED:
+ return "A type variable is not in scope";
+ default:
+ assert this.isValid();
+ throw new Unreachable("Should not throw an error for a valid signature");
+ }
+ }
}
private final AppView<?> appView;
private final Mode mode;
+ private final GenericSignatureContextBuilder contextBuilder;
- private GenericSignatureCorrectnessHelper(AppView<?> appView, Mode mode) {
+ private GenericSignatureCorrectnessHelper(
+ AppView<?> appView, GenericSignatureContextBuilder contextBuilder, Mode mode) {
this.appView = appView;
+ this.contextBuilder = contextBuilder;
this.mode = mode;
}
- public static GenericSignatureCorrectnessHelper createForInitialCheck(AppView<?> appView) {
- return new GenericSignatureCorrectnessHelper(appView, Mode.MARK_AS_INVALID);
+ public static GenericSignatureCorrectnessHelper createForInitialCheck(
+ AppView<?> appView, GenericSignatureContextBuilder contextBuilder) {
+ return new GenericSignatureCorrectnessHelper(appView, contextBuilder, Mode.CLEAR_IF_INVALID);
}
- public static GenericSignatureCorrectnessHelper createForVerification(AppView<?> appView) {
- return new GenericSignatureCorrectnessHelper(appView, Mode.VERIFY);
+ public static GenericSignatureCorrectnessHelper createForVerification(
+ AppView<?> appView, GenericSignatureContextBuilder contextBuilder) {
+ return new GenericSignatureCorrectnessHelper(appView, contextBuilder, Mode.VERIFY);
}
- public void run() {
- appView.appInfo().classes().forEach(this::evaluateSignaturesForClass);
+ public SignatureEvaluationResult run(List<DexProgramClass> programClasses) {
+ if (appView.options().disableGenericSignatureValidation) {
+ return VALID;
+ }
+ for (DexProgramClass clazz : programClasses) {
+ SignatureEvaluationResult evaluationResult = evaluateSignaturesForClass(clazz);
+ if (evaluationResult.isInvalid()) {
+ return evaluationResult;
+ }
+ }
+ return VALID;
}
public SignatureEvaluationResult evaluateSignaturesForClass(DexProgramClass clazz) {
+ if (appView.options().disableGenericSignatureValidation) {
+ return VALID;
+ }
+
+ TypeParameterContext typeParameterContext =
+ contextBuilder.computeTypeParameterContext(appView, clazz.type, alwaysFalse());
+
GenericSignatureContextEvaluator genericSignatureContextEvaluator =
- new GenericSignatureContextEvaluator(appView, clazz, mode);
- ClassSignature classSignature = clazz.getClassSignature();
- SignatureEvaluationResult result = VALID;
- if (classSignature.hasNoSignature() || !classSignature.isInvalid()) {
- result = genericSignatureContextEvaluator.evaluateClassSignature(classSignature);
- if (result.isInvalid() && mode.markAsInvalid()) {
- clazz.setClassSignature(classSignature.toInvalid());
- }
+ new GenericSignatureContextEvaluator(appView, mode, clazz);
+
+ SignatureEvaluationResult result =
+ genericSignatureContextEvaluator.evaluateClassSignatureForContext(typeParameterContext);
+ if (result.isInvalid() && mode.clearIfInvalid()) {
+ appView
+ .options()
+ .reporter
+ .info(
+ GenericSignatureValidationDiagnostic.invalidClassSignature(
+ clazz.getClassSignature().toString(),
+ clazz.getTypeName(),
+ clazz.getOrigin(),
+ result));
+ clazz.clearClassSignature();
}
for (DexEncodedMethod method : clazz.methods()) {
- SignatureEvaluationResult methodResult =
- evaluate(
- method::getGenericSignature,
- genericSignatureContextEvaluator::visitMethodSignature,
- method::setGenericSignature);
- if (result.isValid() && methodResult.isInvalid()) {
- result = methodResult;
- }
+ result =
+ result.combine(
+ evaluate(
+ method::getGenericSignature,
+ methodSignature ->
+ genericSignatureContextEvaluator.visitMethodSignature(
+ methodSignature, typeParameterContext),
+ invalidResult -> {
+ appView
+ .options()
+ .reporter
+ .info(
+ GenericSignatureValidationDiagnostic.invalidMethodSignature(
+ method.getGenericSignature().toString(),
+ method.toSourceString(),
+ clazz.getOrigin(),
+ invalidResult));
+ method.clearGenericSignature();
+ }));
}
for (DexEncodedField field : clazz.fields()) {
- SignatureEvaluationResult fieldResult =
- evaluate(
- field::getGenericSignature,
- genericSignatureContextEvaluator::visitFieldTypeSignature,
- field::setGenericSignature);
- if (result.isValid() && fieldResult.isInvalid()) {
- result = fieldResult;
- }
+ result =
+ result.combine(
+ evaluate(
+ field::getGenericSignature,
+ fieldSignature ->
+ genericSignatureContextEvaluator.visitFieldTypeSignature(
+ fieldSignature, typeParameterContext),
+ invalidResult -> {
+ appView
+ .options()
+ .reporter
+ .info(
+ GenericSignatureValidationDiagnostic.invalidFieldSignature(
+ field.getGenericSignature().toString(),
+ field.toSourceString(),
+ clazz.getOrigin(),
+ invalidResult));
+ field.clearGenericSignature();
+ }));
}
return result;
}
@SuppressWarnings("unchecked")
private <T extends DexDefinitionSignature<?>> SignatureEvaluationResult evaluate(
- Supplier<T> getter, Function<T, SignatureEvaluationResult> evaluate, Consumer<T> setter) {
+ Supplier<T> getter,
+ Function<T, SignatureEvaluationResult> evaluate,
+ Consumer<SignatureEvaluationResult> invalidAction) {
T signature = getter.get();
if (signature.hasNoSignature() || signature.isInvalid()) {
// Already marked as invalid, do nothing
@@ -120,8 +195,8 @@
}
SignatureEvaluationResult signatureResult = evaluate.apply(signature);
assert signatureResult.isValid() || mode.doNotVerify();
- if (signatureResult.isInvalid() && mode.doNotVerify()) {
- setter.accept((T) signature.toInvalid());
+ if (signatureResult.isInvalid() && mode.clearIfInvalid()) {
+ invalidAction.accept(signatureResult);
}
return signatureResult;
}
@@ -130,39 +205,39 @@
private final AppView<?> appView;
private final DexProgramClass context;
- private final Set<String> classFormalTypeParameters = new HashSet<>();
- private final Set<String> methodTypeArguments = new HashSet<>();
private final Mode mode;
- public GenericSignatureContextEvaluator(
- AppView<?> appView, DexProgramClass context, Mode mode) {
+ private GenericSignatureContextEvaluator(
+ AppView<?> appView, Mode mode, DexProgramClass context) {
this.appView = appView;
- this.context = context;
this.mode = mode;
+ this.context = context;
}
- private SignatureEvaluationResult evaluateClassSignature(ClassSignature classSignature) {
- classSignature
- .getFormalTypeParameters()
- .forEach(param -> classFormalTypeParameters.add(param.name));
- if (classSignature.hasNoSignature()) {
+ private SignatureEvaluationResult evaluateClassSignatureForContext(
+ TypeParameterContext typeParameterContext) {
+ ClassSignature classSignature = context.classSignature;
+ if (classSignature.hasNoSignature() || classSignature.isInvalid()) {
return VALID;
}
SignatureEvaluationResult signatureEvaluationResult =
- evaluateFormalTypeParameters(classSignature.formalTypeParameters);
+ evaluateFormalTypeParameters(classSignature.formalTypeParameters, typeParameterContext);
if (signatureEvaluationResult.isInvalid()) {
return signatureEvaluationResult;
}
- if ((context.superType != appView.dexItemFactory().objectType
- && context.superType != classSignature.superClassSignature().type())
- || (context.superType == appView.dexItemFactory().objectType
- && classSignature.superClassSignature().hasNoSignature())) {
+ if (context.superType == appView.dexItemFactory().objectType
+ && classSignature.superClassSignature().hasNoSignature()) {
+ // We represent no signature as object.
+ } else if (context.superType
+ != appView.graphLens().lookupClassType(classSignature.superClassSignature().type())) {
assert mode.doNotVerify();
return INVALID_SUPER_TYPE;
}
signatureEvaluationResult =
evaluateTypeArgumentsAppliedToType(
- classSignature.superClassSignature().typeArguments(), context.superType);
+ classSignature.superClassSignature().typeArguments(),
+ context.superType,
+ typeParameterContext);
if (signatureEvaluationResult.isInvalid()) {
return signatureEvaluationResult;
}
@@ -175,7 +250,7 @@
for (int i = 0; i < actualInterfaces.length; i++) {
signatureEvaluationResult =
evaluateTypeArgumentsAppliedToType(
- superInterfaces.get(i).typeArguments(), actualInterfaces[i]);
+ superInterfaces.get(i).typeArguments(), actualInterfaces[i], typeParameterContext);
if (signatureEvaluationResult.isInvalid()) {
return signatureEvaluationResult;
}
@@ -183,37 +258,46 @@
return VALID;
}
- private SignatureEvaluationResult visitMethodSignature(MethodTypeSignature methodSignature) {
- methodSignature
- .getFormalTypeParameters()
- .forEach(param -> methodTypeArguments.add(param.name));
+ private SignatureEvaluationResult visitMethodSignature(
+ MethodTypeSignature methodSignature, TypeParameterContext typeParameterContext) {
+ // If the class context is invalid, we cannot reason about the method signatures.
+ if (context.classSignature.isInvalid()) {
+ return VALID;
+ }
+ TypeParameterContext methodContext =
+ methodSignature.formalTypeParameters.isEmpty()
+ ? typeParameterContext
+ : typeParameterContext.addLiveParameters(
+ ListUtils.map(
+ methodSignature.getFormalTypeParameters(), FormalTypeParameter::getName));
SignatureEvaluationResult evaluateResult =
- evaluateFormalTypeParameters(methodSignature.getFormalTypeParameters());
+ evaluateFormalTypeParameters(methodSignature.getFormalTypeParameters(), methodContext);
if (evaluateResult.isInvalid()) {
return evaluateResult;
}
- evaluateResult = evaluateTypeArguments(methodSignature.typeSignatures);
+ evaluateResult = evaluateTypeArguments(methodSignature.typeSignatures, methodContext);
if (evaluateResult.isInvalid()) {
return evaluateResult;
}
- evaluateResult = evaluateTypeArguments(methodSignature.throwsSignatures);
+ evaluateResult = evaluateTypeArguments(methodSignature.throwsSignatures, methodContext);
if (evaluateResult.isInvalid()) {
return evaluateResult;
}
ReturnType returnType = methodSignature.returnType();
if (!returnType.isVoidDescriptor()) {
- evaluateResult = evaluateTypeArgument(returnType.typeSignature());
+ evaluateResult = evaluateTypeArgument(returnType.typeSignature(), methodContext);
if (evaluateResult.isInvalid()) {
return evaluateResult;
}
}
- methodTypeArguments.clear();
return evaluateResult;
}
- private SignatureEvaluationResult evaluateTypeArguments(List<TypeSignature> typeSignatures) {
+ private SignatureEvaluationResult evaluateTypeArguments(
+ List<TypeSignature> typeSignatures, TypeParameterContext typeParameterContext) {
for (TypeSignature typeSignature : typeSignatures) {
- SignatureEvaluationResult signatureEvaluationResult = evaluateTypeArgument(typeSignature);
+ SignatureEvaluationResult signatureEvaluationResult =
+ evaluateTypeArgument(typeSignature, typeParameterContext);
if (signatureEvaluationResult.isInvalid()) {
return signatureEvaluationResult;
}
@@ -221,14 +305,20 @@
return VALID;
}
- private SignatureEvaluationResult visitFieldTypeSignature(FieldTypeSignature fieldSignature) {
- return evaluateTypeArgument(fieldSignature);
+ private SignatureEvaluationResult visitFieldTypeSignature(
+ FieldTypeSignature fieldSignature, TypeParameterContext typeParameterContext) {
+ // If the class context is invalid, we cannot reason about the method signatures.
+ if (context.classSignature.isInvalid()) {
+ return VALID;
+ }
+ return evaluateTypeArgument(fieldSignature, typeParameterContext);
}
private SignatureEvaluationResult evaluateFormalTypeParameters(
- List<FormalTypeParameter> typeParameters) {
+ List<FormalTypeParameter> typeParameters, TypeParameterContext typeParameterContext) {
for (FormalTypeParameter typeParameter : typeParameters) {
- SignatureEvaluationResult evaluationResult = evaluateTypeParameter(typeParameter);
+ SignatureEvaluationResult evaluationResult =
+ evaluateTypeParameter(typeParameter, typeParameterContext);
if (evaluationResult.isInvalid()) {
return evaluationResult;
}
@@ -236,66 +326,79 @@
return VALID;
}
- private SignatureEvaluationResult evaluateTypeParameter(FormalTypeParameter typeParameter) {
- SignatureEvaluationResult evaluationResult = evaluateTypeArgument(typeParameter.classBound);
+ private SignatureEvaluationResult evaluateTypeParameter(
+ FormalTypeParameter typeParameter, TypeParameterContext typeParameterContext) {
+ SignatureEvaluationResult evaluationResult =
+ evaluateTypeArgument(typeParameter.classBound, typeParameterContext);
if (evaluationResult.isInvalid()) {
return evaluationResult;
}
- if (typeParameter.interfaceBounds != null) {
- for (FieldTypeSignature interfaceBound : typeParameter.interfaceBounds) {
- evaluationResult = evaluateTypeArgument(interfaceBound);
- if (evaluationResult != VALID) {
- return evaluationResult;
- }
+ for (FieldTypeSignature interfaceBound : typeParameter.interfaceBounds) {
+ evaluationResult = evaluateTypeArgument(interfaceBound, typeParameterContext);
+ if (evaluationResult != VALID) {
+ return evaluationResult;
}
}
return VALID;
}
- private SignatureEvaluationResult evaluateTypeArgument(TypeSignature typeSignature) {
+ private SignatureEvaluationResult evaluateTypeArgument(
+ TypeSignature typeSignature, TypeParameterContext typeParameterContext) {
if (typeSignature.isBaseTypeSignature()) {
return VALID;
}
FieldTypeSignature fieldTypeSignature = typeSignature.asFieldTypeSignature();
- if (fieldTypeSignature.hasNoSignature()) {
+ if (fieldTypeSignature.hasNoSignature() || fieldTypeSignature.isStar()) {
return VALID;
}
if (fieldTypeSignature.isTypeVariableSignature()) {
// This is in an applied position, just check that the variable is registered.
String typeVariable = fieldTypeSignature.asTypeVariableSignature().typeVariable();
- if (classFormalTypeParameters.contains(typeVariable)
- || methodTypeArguments.contains(typeVariable)) {
+ if (typeParameterContext.isLiveParameter(typeVariable)) {
return VALID;
}
assert mode.doNotVerify();
return INVALID_TYPE_VARIABLE_UNDEFINED;
}
if (fieldTypeSignature.isArrayTypeSignature()) {
- return evaluateTypeArgument(fieldTypeSignature.asArrayTypeSignature().elementSignature());
+ return evaluateTypeArgument(
+ fieldTypeSignature.asArrayTypeSignature().elementSignature(), typeParameterContext);
}
assert fieldTypeSignature.isClassTypeSignature();
- return evaluateTypeArguments(fieldTypeSignature.asClassTypeSignature());
+ return evaluateTypeArguments(fieldTypeSignature.asClassTypeSignature(), typeParameterContext);
}
- private SignatureEvaluationResult evaluateTypeArguments(ClassTypeSignature classTypeSignature) {
+ private SignatureEvaluationResult evaluateTypeArguments(
+ ClassTypeSignature classTypeSignature, TypeParameterContext typeParameterContext) {
return evaluateTypeArgumentsAppliedToType(
- classTypeSignature.typeArguments, classTypeSignature.type());
+ classTypeSignature.typeArguments, classTypeSignature.type(), typeParameterContext);
}
private SignatureEvaluationResult evaluateTypeArgumentsAppliedToType(
- List<FieldTypeSignature> typeArguments, DexType type) {
+ List<FieldTypeSignature> typeArguments,
+ DexType type,
+ TypeParameterContext typeParameterContext) {
for (FieldTypeSignature typeArgument : typeArguments) {
- SignatureEvaluationResult evaluationResult = evaluateTypeArgument(typeArgument);
+ SignatureEvaluationResult evaluationResult =
+ evaluateTypeArgument(typeArgument, typeParameterContext);
if (evaluationResult.isInvalid()) {
assert mode.doNotVerify();
return evaluationResult;
}
}
- DexClass clazz = appView.definitionFor(type);
+ // TODO(b/187035453): We should visit generic signatures in the enqueuer.
+ DexClass clazz =
+ appView
+ .appInfo()
+ .definitionForWithoutExistenceAssert(appView.graphLens().lookupClassType(type));
if (clazz == null) {
// We do not know if the application of arguments works or not.
return VALID;
}
+ if (typeArguments.isEmpty()) {
+ // When type arguments are empty we are using the raw type.
+ return VALID;
+ }
if (typeArguments.size() != clazz.classSignature.getFormalTypeParameters().size()) {
assert mode.doNotVerify();
return INVALID_APPLICATION_COUNT;
diff --git a/src/main/java/com/android/tools/r8/graph/GenericSignatureDiagnostic.java b/src/main/java/com/android/tools/r8/graph/GenericSignatureFormatDiagnostic.java
similarity index 78%
rename from src/main/java/com/android/tools/r8/graph/GenericSignatureDiagnostic.java
rename to src/main/java/com/android/tools/r8/graph/GenericSignatureFormatDiagnostic.java
index fa95bce..6729890 100644
--- a/src/main/java/com/android/tools/r8/graph/GenericSignatureDiagnostic.java
+++ b/src/main/java/com/android/tools/r8/graph/GenericSignatureFormatDiagnostic.java
@@ -9,13 +9,13 @@
import com.android.tools.r8.position.Position;
import java.lang.reflect.GenericSignatureFormatError;
-public class GenericSignatureDiagnostic implements Diagnostic {
+public class GenericSignatureFormatDiagnostic implements Diagnostic {
private final Origin origin;
private final Position position;
private final String message;
- GenericSignatureDiagnostic(Origin origin, Position position, String message) {
+ GenericSignatureFormatDiagnostic(Origin origin, Position position, String message) {
this.origin = origin;
this.position = position;
this.message = message;
@@ -36,22 +36,22 @@
return message;
}
- static GenericSignatureDiagnostic invalidClassSignature(
+ static GenericSignatureFormatDiagnostic invalidClassSignature(
String signature, String name, Origin origin, GenericSignatureFormatError error) {
return invalidSignature(signature, "class", name, origin, error);
}
- static GenericSignatureDiagnostic invalidMethodSignature(
+ static GenericSignatureFormatDiagnostic invalidMethodSignature(
String signature, String name, Origin origin, GenericSignatureFormatError error) {
return invalidSignature(signature, "method", name, origin, error);
}
- static GenericSignatureDiagnostic invalidFieldSignature(
+ static GenericSignatureFormatDiagnostic invalidFieldSignature(
String signature, String name, Origin origin, GenericSignatureFormatError error) {
return invalidSignature(signature, "field", name, origin, error);
}
- private static GenericSignatureDiagnostic invalidSignature(
+ private static GenericSignatureFormatDiagnostic invalidSignature(
String signature,
String kind,
String name,
@@ -70,6 +70,6 @@
+ System.lineSeparator()
+ "Parser error: "
+ error.getMessage();
- return new GenericSignatureDiagnostic(origin, Position.UNKNOWN, message);
+ return new GenericSignatureFormatDiagnostic(origin, Position.UNKNOWN, message);
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/GenericSignaturePartialTypeArgumentApplier.java b/src/main/java/com/android/tools/r8/graph/GenericSignaturePartialTypeArgumentApplier.java
index c381074..56a6496 100644
--- a/src/main/java/com/android/tools/r8/graph/GenericSignaturePartialTypeArgumentApplier.java
+++ b/src/main/java/com/android/tools/r8/graph/GenericSignaturePartialTypeArgumentApplier.java
@@ -14,52 +14,37 @@
import com.android.tools.r8.graph.GenericSignature.ReturnType;
import com.android.tools.r8.graph.GenericSignature.TypeSignature;
import com.android.tools.r8.graph.GenericSignature.WildcardIndicator;
+import com.android.tools.r8.graph.GenericSignatureContextBuilder.TypeParameterContext;
import com.android.tools.r8.utils.ListUtils;
-import com.google.common.collect.ImmutableSet;
-import java.util.Collections;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
public class GenericSignaturePartialTypeArgumentApplier implements GenericSignatureVisitor {
- private final Map<String, DexType> substitutions;
- private final Set<String> liveTypeVariables;
- private final DexType objectType;
+ private final TypeParameterContext typeParameterContext;
private final BiPredicate<DexType, DexType> enclosingPruned;
private final Predicate<DexType> hasGenericTypeParameters;
+ private final AppView<?> appView;
private GenericSignaturePartialTypeArgumentApplier(
- Map<String, DexType> substitutions,
- Set<String> liveTypeVariables,
- DexType objectType,
+ AppView<?> appView,
+ TypeParameterContext typeParameterContext,
BiPredicate<DexType, DexType> enclosingPruned,
Predicate<DexType> hasGenericTypeParameters) {
- this.substitutions = substitutions;
- this.liveTypeVariables = liveTypeVariables;
- this.objectType = objectType;
+ this.appView = appView;
+ this.typeParameterContext = typeParameterContext;
this.enclosingPruned = enclosingPruned;
this.hasGenericTypeParameters = hasGenericTypeParameters;
}
public static GenericSignaturePartialTypeArgumentApplier build(
- DexType objectType,
+ AppView<?> appView,
+ TypeParameterContext typeParameterContext,
BiPredicate<DexType, DexType> enclosingPruned,
Predicate<DexType> hasGenericTypeParameters) {
return new GenericSignaturePartialTypeArgumentApplier(
- Collections.emptyMap(),
- Collections.emptySet(),
- objectType,
- enclosingPruned,
- hasGenericTypeParameters);
- }
-
- public GenericSignaturePartialTypeArgumentApplier addSubstitutionsAndVariables(
- Map<String, DexType> substitutions, Set<String> liveTypeVariables) {
- return new GenericSignaturePartialTypeArgumentApplier(
- substitutions, liveTypeVariables, objectType, enclosingPruned, hasGenericTypeParameters);
+ appView, typeParameterContext, enclosingPruned, hasGenericTypeParameters);
}
public GenericSignaturePartialTypeArgumentApplier buildForMethod(
@@ -67,23 +52,27 @@
if (formals.isEmpty()) {
return this;
}
- ImmutableSet.Builder<String> liveVariablesBuilder = ImmutableSet.builder();
- liveVariablesBuilder.addAll(liveTypeVariables);
- formals.forEach(
- formal -> {
- liveVariablesBuilder.add(formal.name);
- });
return new GenericSignaturePartialTypeArgumentApplier(
- substitutions, liveTypeVariables, objectType, enclosingPruned, hasGenericTypeParameters);
+ appView,
+ typeParameterContext.addLiveParameters(
+ ListUtils.map(formals, FormalTypeParameter::getName)),
+ enclosingPruned,
+ hasGenericTypeParameters);
}
@Override
public ClassSignature visitClassSignature(ClassSignature classSignature) {
+ if (classSignature.hasNoSignature() || classSignature.isInvalid()) {
+ return classSignature;
+ }
return classSignature.visit(this);
}
@Override
public MethodTypeSignature visitMethodSignature(MethodTypeSignature methodSignature) {
+ if (methodSignature.hasNoSignature() || methodSignature.isInvalid()) {
+ return methodSignature;
+ }
return methodSignature.visit(this);
}
@@ -111,7 +100,7 @@
@Override
public List<FieldTypeSignature> visitInterfaceBounds(List<FieldTypeSignature> fieldSignatures) {
- if (fieldSignatures == null || fieldSignatures.isEmpty()) {
+ if (fieldSignatures.isEmpty()) {
return fieldSignatures;
}
return ListUtils.mapOrElse(fieldSignatures, this::visitFieldTypeSignature);
@@ -142,6 +131,9 @@
@Override
public FieldTypeSignature visitClassBound(FieldTypeSignature fieldSignature) {
+ if (fieldSignature.hasNoSignature()) {
+ return fieldSignature;
+ }
return visitFieldTypeSignature(fieldSignature);
}
@@ -205,6 +197,9 @@
@Override
public FieldTypeSignature visitFieldTypeSignature(FieldTypeSignature fieldSignature) {
+ if (fieldSignature.hasNoSignature() || fieldSignature.isInvalid()) {
+ return fieldSignature;
+ }
if (fieldSignature.isStar()) {
return fieldSignature;
} else if (fieldSignature.isClassTypeSignature()) {
@@ -214,11 +209,10 @@
} else {
assert fieldSignature.isTypeVariableSignature();
String typeVariableName = fieldSignature.asTypeVariableSignature().typeVariable();
- if (substitutions.containsKey(typeVariableName)
- && !liveTypeVariables.contains(typeVariableName)) {
- DexType substitution = substitutions.get(typeVariableName);
+ if (!typeParameterContext.isLiveParameter(typeVariableName)) {
+ DexType substitution = typeParameterContext.getPrunedSubstitution(typeVariableName);
if (substitution == null) {
- substitution = objectType;
+ substitution = appView.dexItemFactory().objectType;
}
return new ClassTypeSignature(substitution).asArgument(WildcardIndicator.NONE);
}
diff --git a/src/main/java/com/android/tools/r8/graph/GenericSignaturePrinter.java b/src/main/java/com/android/tools/r8/graph/GenericSignaturePrinter.java
index d04e3af..b111c57 100644
--- a/src/main/java/com/android/tools/r8/graph/GenericSignaturePrinter.java
+++ b/src/main/java/com/android/tools/r8/graph/GenericSignaturePrinter.java
@@ -87,15 +87,15 @@
@Override
public FieldTypeSignature visitClassBound(FieldTypeSignature fieldSignature) {
sb.append(":");
+ if (fieldSignature.hasNoSignature()) {
+ return fieldSignature;
+ }
printFieldTypeSignature(fieldSignature, false);
return fieldSignature;
}
@Override
public List<FieldTypeSignature> visitInterfaceBounds(List<FieldTypeSignature> fieldSignatures) {
- if (fieldSignatures == null) {
- return null;
- }
fieldSignatures.forEach(this::visitInterfaceBound);
return fieldSignatures;
}
diff --git a/src/main/java/com/android/tools/r8/graph/GenericSignatureTypeRewriter.java b/src/main/java/com/android/tools/r8/graph/GenericSignatureTypeRewriter.java
index da35877..332aa8d 100644
--- a/src/main/java/com/android/tools/r8/graph/GenericSignatureTypeRewriter.java
+++ b/src/main/java/com/android/tools/r8/graph/GenericSignatureTypeRewriter.java
@@ -212,12 +212,15 @@
@Override
public FieldTypeSignature visitClassBound(FieldTypeSignature fieldSignature) {
+ if (fieldSignature.hasNoSignature()) {
+ return fieldSignature;
+ }
return visitFieldTypeSignature(fieldSignature);
}
@Override
public List<FieldTypeSignature> visitInterfaceBounds(List<FieldTypeSignature> fieldSignatures) {
- if (fieldSignatures == null || fieldSignatures.isEmpty()) {
+ if (fieldSignatures.isEmpty()) {
return fieldSignatures;
}
return ListUtils.mapOrElse(fieldSignatures, this::visitFieldTypeSignature);
diff --git a/src/main/java/com/android/tools/r8/graph/GenericSignatureTypeVisitor.java b/src/main/java/com/android/tools/r8/graph/GenericSignatureTypeVisitor.java
index c6d0e6a..59cd879 100644
--- a/src/main/java/com/android/tools/r8/graph/GenericSignatureTypeVisitor.java
+++ b/src/main/java/com/android/tools/r8/graph/GenericSignatureTypeVisitor.java
@@ -69,14 +69,14 @@
@Override
public FieldTypeSignature visitClassBound(FieldTypeSignature fieldSignature) {
+ if (fieldSignature.hasNoSignature()) {
+ return fieldSignature;
+ }
return visitFieldTypeSignature(fieldSignature);
}
@Override
public List<FieldTypeSignature> visitInterfaceBounds(List<FieldTypeSignature> fieldSignatures) {
- if (fieldSignatures == null) {
- return null;
- }
fieldSignatures.forEach(this::visitInterfaceBound);
return fieldSignatures;
}
diff --git a/src/main/java/com/android/tools/r8/graph/GenericSignatureValidationDiagnostic.java b/src/main/java/com/android/tools/r8/graph/GenericSignatureValidationDiagnostic.java
new file mode 100644
index 0000000..4a85abd
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/GenericSignatureValidationDiagnostic.java
@@ -0,0 +1,72 @@
+// Copyright (c) 2020, 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.graph;
+
+import com.android.tools.r8.Diagnostic;
+import com.android.tools.r8.graph.GenericSignatureCorrectnessHelper.SignatureEvaluationResult;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
+
+public class GenericSignatureValidationDiagnostic implements Diagnostic {
+
+ private final Origin origin;
+ private final Position position;
+ private final String message;
+
+ GenericSignatureValidationDiagnostic(Origin origin, Position position, String message) {
+ this.origin = origin;
+ this.position = position;
+ this.message = message;
+ }
+
+ @Override
+ public Origin getOrigin() {
+ return origin;
+ }
+
+ @Override
+ public Position getPosition() {
+ return position;
+ }
+
+ @Override
+ public String getDiagnosticMessage() {
+ return message;
+ }
+
+ static GenericSignatureValidationDiagnostic invalidClassSignature(
+ String signature, String name, Origin origin, SignatureEvaluationResult error) {
+ return invalidSignature(signature, "class", name, origin, error);
+ }
+
+ static GenericSignatureValidationDiagnostic invalidMethodSignature(
+ String signature, String name, Origin origin, SignatureEvaluationResult error) {
+ return invalidSignature(signature, "method", name, origin, error);
+ }
+
+ static GenericSignatureValidationDiagnostic invalidFieldSignature(
+ String signature, String name, Origin origin, SignatureEvaluationResult error) {
+ return invalidSignature(signature, "field", name, origin, error);
+ }
+
+ private static GenericSignatureValidationDiagnostic invalidSignature(
+ String signature, String kind, String name, Origin origin, SignatureEvaluationResult error) {
+ String message =
+ "Invalid signature '"
+ + signature
+ + "' for "
+ + kind
+ + " "
+ + name
+ + "."
+ + System.lineSeparator()
+ + "Validation error: "
+ + error.getDescription()
+ + "."
+ + System.lineSeparator()
+ + "Signature is ignored and will not be present in the output.";
+ return new GenericSignatureValidationDiagnostic(origin, Position.UNKNOWN, message);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
index b0df7c7..bd95f96 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
@@ -30,7 +30,9 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexValue.DexValueInt;
import com.android.tools.r8.graph.FieldAccessFlags;
+import com.android.tools.r8.graph.GenericSignature.ClassTypeSignature;
import com.android.tools.r8.graph.GenericSignature.FieldTypeSignature;
+import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.MethodCollection;
@@ -70,10 +72,12 @@
private final InterfaceMethodRewriter rewriter;
private final Map<DexProgramClass, PostProcessingInterfaceInfo> postProcessingInterfaceInfos =
new ConcurrentHashMap<>();
+ private final ClassTypeSignature objectTypeSignature;
InterfaceProcessor(AppView<?> appView, InterfaceMethodRewriter rewriter) {
this.appView = appView;
this.rewriter = rewriter;
+ this.objectTypeSignature = new ClassTypeSignature(appView.dexItemFactory().objectType);
}
@Override
@@ -129,6 +133,8 @@
appView,
builder -> {
builder.setSourceFile(iface.sourceFile);
+ builder.setGenericSignature(
+ iface.getClassSignature().toObjectBoundWithSameFormals(objectTypeSignature));
ensureCompanionClassInitializesInterface(iface, builder);
processVirtualInterfaceMethods(iface, builder);
processDirectInterfaceMethods(iface, builder);
@@ -260,7 +266,7 @@
.setName(companionMethod.getName())
.setProto(companionMethod.getProto())
.setAccessFlags(newFlags)
- .setGenericSignature(virtual.getGenericSignature())
+ .setGenericSignature(MethodTypeSignature.noSignature())
.setAnnotations(virtual.annotations())
.setParameterAnnotationsList(virtual.getParameterAnnotations())
.setCode(ignored -> virtual.getCode())
diff --git a/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java b/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
index c44e4e7..16b6508 100644
--- a/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
+++ b/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
@@ -4,23 +4,37 @@
package com.android.tools.r8.naming.signature;
+import static com.google.common.base.Predicates.alwaysFalse;
+
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GenericSignatureContextBuilder;
+import com.android.tools.r8.graph.GenericSignaturePartialTypeArgumentApplier;
import com.android.tools.r8.graph.GenericSignatureTypeRewriter;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.utils.ThreadUtils;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
+import java.util.function.BiPredicate;
+import java.util.function.Predicate;
// TODO(b/169516860): We should generalize this to handle rewriting of attributes in general.
public class GenericSignatureRewriter {
private final AppView<?> appView;
private final NamingLens namingLens;
+ private final GenericSignatureContextBuilder contextBuilder;
public GenericSignatureRewriter(AppView<?> appView, NamingLens namingLens) {
+ this(appView, namingLens, null);
+ }
+
+ public GenericSignatureRewriter(
+ AppView<?> appView, NamingLens namingLens, GenericSignatureContextBuilder contextBuilder) {
this.appView = appView;
this.namingLens = namingLens;
+ this.contextBuilder = contextBuilder;
}
public void run(Iterable<? extends DexProgramClass> classes, ExecutorService executorService)
@@ -34,20 +48,54 @@
// arguments. If that is the case, the ProguardMapMinifier will pass in all classes that is
// either ProgramClass or has a mapping. This is then transitively called inside the
// ClassNameMinifier.
+ Predicate<DexType> wasPruned =
+ appView.hasLiveness() ? appView.withLiveness().appInfo()::wasPruned : alwaysFalse();
+ BiPredicate<DexType, DexType> hasPrunedRelationship =
+ (enclosing, enclosed) ->
+ contextBuilder.hasPrunedRelationship(appView, enclosing, enclosed, wasPruned);
+ Predicate<DexType> hasGenericTypeVariables =
+ type -> contextBuilder.hasGenericTypeVariables(appView, type, wasPruned);
ThreadUtils.processItems(
classes,
clazz -> {
+ GenericSignaturePartialTypeArgumentApplier classArgumentApplier =
+ contextBuilder != null
+ ? GenericSignaturePartialTypeArgumentApplier.build(
+ appView,
+ contextBuilder.computeTypeParameterContext(
+ appView, clazz.getType(), wasPruned),
+ hasPrunedRelationship,
+ hasGenericTypeVariables)
+ : null;
GenericSignatureTypeRewriter genericSignatureTypeRewriter =
new GenericSignatureTypeRewriter(appView, clazz);
- clazz.setClassSignature(genericSignatureTypeRewriter.rewrite(clazz.getClassSignature()));
+ clazz.setClassSignature(
+ genericSignatureTypeRewriter.rewrite(
+ classArgumentApplier != null
+ ? classArgumentApplier.visitClassSignature(clazz.getClassSignature())
+ : clazz.getClassSignature()));
clazz.forEachField(
field ->
field.setGenericSignature(
- genericSignatureTypeRewriter.rewrite(field.getGenericSignature())));
+ genericSignatureTypeRewriter.rewrite(
+ classArgumentApplier != null
+ ? classArgumentApplier.visitFieldTypeSignature(
+ field.getGenericSignature())
+ : field.getGenericSignature())));
clazz.forEachMethod(
- method ->
- method.setGenericSignature(
- genericSignatureTypeRewriter.rewrite(method.getGenericSignature())));
+ method -> {
+ // The reflection api do not distinguish static methods context and
+ // from virtual methods we therefore always base the context for a method on
+ // the class context.
+ method.setGenericSignature(
+ genericSignatureTypeRewriter.rewrite(
+ classArgumentApplier != null
+ ? classArgumentApplier
+ .buildForMethod(
+ method.getGenericSignature().getFormalTypeParameters())
+ .visitMethodSignature(method.getGenericSignature())
+ : method.getGenericSignature()));
+ });
},
executorService);
}
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceElement.java b/src/main/java/com/android/tools/r8/retrace/RetraceElement.java
index cb2ac8c..55de558 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceElement.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceElement.java
@@ -3,11 +3,14 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.retrace;
+import com.android.tools.r8.KeepForSubclassing;
+
/**
* Base interface for any element in a retrace result.
*
* <p>The element represents an unambiguous retracing.
*/
+@KeepForSubclassing
public interface RetraceElement<R extends RetraceResult<?>> {
R getRetraceResultContext();
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java
index ef3b4d2..8e78b09 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java
@@ -44,6 +44,7 @@
private List<DexEncodedMethod> directMethods = new ArrayList<>();
private List<DexEncodedMethod> virtualMethods = new ArrayList<>();
private List<SyntheticMethodBuilder> methods = new ArrayList<>();
+ private ClassSignature signature = ClassSignature.noSignature();
SyntheticClassBuilder(DexType type, SynthesizingContext context, DexItemFactory factory) {
this.factory = factory;
@@ -87,6 +88,11 @@
return self();
}
+ public B setGenericSignature(ClassSignature signature) {
+ this.signature = signature;
+ return self();
+ }
+
public B setStaticFields(List<DexEncodedField> fields) {
staticFields.clear();
staticFields.addAll(fields);
@@ -153,7 +159,7 @@
nestMembers,
enclosingMembers,
innerClasses,
- ClassSignature.noSignature(),
+ signature,
DexAnnotationSet.empty(),
staticFields.toArray(DexEncodedField.EMPTY_ARRAY),
instanceFields.toArray(DexEncodedField.EMPTY_ARRAY),
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 849d641..854e8c48 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -657,6 +657,7 @@
public boolean ignoreMissingClasses = false;
public boolean reportMissingClassesInEnclosingMethodAttribute = false;
public boolean reportMissingClassesInInnerClassAttributes = false;
+ public boolean disableGenericSignatureValidation = false;
// EXPERIMENTAL flag to get behaviour as close to Proguard as possible.
public boolean forceProguardCompatibility = false;
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index b24d16a..789da90 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -7,6 +7,7 @@
import static com.android.tools.r8.TestBuilder.getTestingAnnotations;
import static com.android.tools.r8.utils.InternalOptions.ASM_VERSION;
import static com.google.common.collect.Lists.cartesianProduct;
+import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -1827,4 +1828,22 @@
extractor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
return extractor.getClassFileVersion();
}
+
+ public static void verifyAllInfoFromGenericSignatureTypeParameterValidation(
+ TestCompileResult<?, ?> compileResult) {
+ compileResult.assertAtLeastOneInfoMessage();
+ compileResult.assertAllInfoMessagesMatch(containsString("A type variable is not in scope"));
+ }
+
+ public static void verifyHasInfoFromGenericSignatureTypeParameterValidation(
+ TestCompileResult<?, ?> compileResult) {
+ compileResult.assertInfoMessageThatMatches(containsString("A type variable is not in scope"));
+ }
+
+ public static void verifyExpectedInfoFromGenericSignatureSuperTypeValidation(
+ TestCompileResult<?, ?> compileResult) {
+ compileResult.assertAtLeastOneInfoMessage();
+ compileResult.assertAllInfoMessagesMatch(
+ containsString("The generic super type is not the same as the class super type"));
+ }
}
diff --git a/src/test/java/com/android/tools/r8/cf/bootstrap/BootstrapCurrentEqualityTest.java b/src/test/java/com/android/tools/r8/cf/bootstrap/BootstrapCurrentEqualityTest.java
index a8d57c0..4e9353b 100644
--- a/src/test/java/com/android/tools/r8/cf/bootstrap/BootstrapCurrentEqualityTest.java
+++ b/src/test/java/com/android/tools/r8/cf/bootstrap/BootstrapCurrentEqualityTest.java
@@ -105,7 +105,9 @@
.setMode(mode)
.addProgramFiles(ToolHelper.R8_WITH_RELOCATED_DEPS_JAR)
.addKeepRuleFiles(MAIN_KEEP)
+ .allowDiagnosticInfoMessages()
.compile()
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation)
.apply(c -> FileUtils.writeTextFile(map, c.getProguardMap()))
.writeToZip(jar);
}
diff --git a/src/test/java/com/android/tools/r8/debug/ContinuousKotlinSteppingTest.java b/src/test/java/com/android/tools/r8/debug/ContinuousKotlinSteppingTest.java
index 539af51..c3e45b6 100644
--- a/src/test/java/com/android/tools/r8/debug/ContinuousKotlinSteppingTest.java
+++ b/src/test/java/com/android/tools/r8/debug/ContinuousKotlinSteppingTest.java
@@ -17,7 +17,7 @@
private static final String MAIN_METHOD_NAME = "main";
- @Parameters(name = "{0}")
+ @Parameters(name = "{0}, {1}")
public static List<Object[]> data() {
return buildParameters(
getTestParameters().withDexRuntimes().withAllApiLevels().build(),
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugarLambdaWithAnonymousClass.java b/src/test/java/com/android/tools/r8/desugar/DesugarLambdaWithAnonymousClass.java
index 72549c5..9691b07 100644
--- a/src/test/java/com/android/tools/r8/desugar/DesugarLambdaWithAnonymousClass.java
+++ b/src/test/java/com/android/tools/r8/desugar/DesugarLambdaWithAnonymousClass.java
@@ -29,10 +29,10 @@
@RunWith(Parameterized.class)
public class DesugarLambdaWithAnonymousClass extends TestBase {
- private List<String> EXPECTED_JAVAC_RESULT =
+ private final List<String> EXPECTED_JAVAC_RESULT =
ImmutableList.of("Hello from inside lambda$test$0", "Hello from inside lambda$testStatic$1");
- private List<String> EXPECTED_D8_DESUGARED_RESULT =
+ private final List<String> EXPECTED_D8_DESUGARED_RESULT =
ImmutableList.of(
"Hello from inside lambda$test$0$DesugarLambdaWithAnonymousClass$TestClass",
"Hello from inside lambda$testStatic$1");
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/kotlin/KotlinMetadataTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/kotlin/KotlinMetadataTest.java
index ef8f61a..55e2905 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/kotlin/KotlinMetadataTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/kotlin/KotlinMetadataTest.java
@@ -20,6 +20,7 @@
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
@@ -130,7 +131,7 @@
.addKeepAllClassesRule()
.addKeepAttributes(ProguardKeepAttributes.RUNTIME_VISIBLE_ANNOTATIONS)
.setMinApi(parameters.getApiLevel())
- .allowDiagnosticWarningMessages()
+ .allowDiagnosticMessages()
.allowUnusedDontWarnKotlinReflectJvmInternal(
kotlinParameters.getCompiler().isNot(KOTLINC_1_3_72));
KeepRuleConsumer keepRuleConsumer = null;
@@ -141,6 +142,8 @@
R8TestCompileResult compileResult =
testBuilder
.compile()
+ .assertNoErrorMessages()
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation)
.apply(KotlinMetadataTestBase::verifyExpectedWarningsFromKotlinReflectAndStdLib);
if (desugarLibrary) {
assertNotNull(keepRuleConsumer);
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/Java11R8BootstrapTest.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/Java11R8BootstrapTest.java
index 1eac80e..de1c949 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/Java11R8BootstrapTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/Java11R8BootstrapTest.java
@@ -77,7 +77,9 @@
options.desugarState = DesugarState.ON;
options.cfToCfDesugar = true;
}))
+ .allowDiagnosticInfoMessages()
.compile()
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation)
.inspect(inspector -> assertNests(inspector, desugar))
.writeToZip();
}
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/Java11R8CompilationTest.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/Java11R8CompilationTest.java
index cb549f5..31f7aba 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/Java11R8CompilationTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/Java11R8CompilationTest.java
@@ -50,7 +50,9 @@
.setMinApi(parameters.getApiLevel())
.addProgramFiles(ToolHelper.R8_WITH_RELOCATED_DEPS_11_JAR)
.addKeepRuleFiles(MAIN_KEEP)
+ .allowDiagnosticInfoMessages()
.compile()
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation)
.inspect(this::assertNotEmpty)
.inspect(Java11R8CompilationTest::assertNoNests);
}
diff --git a/src/test/java/com/android/tools/r8/graph/GenericSignatureIdentityTest.java b/src/test/java/com/android/tools/r8/graph/GenericSignatureIdentityTest.java
index f4adbfb..3cb6899 100644
--- a/src/test/java/com/android/tools/r8/graph/GenericSignatureIdentityTest.java
+++ b/src/test/java/com/android/tools/r8/graph/GenericSignatureIdentityTest.java
@@ -78,6 +78,10 @@
if (signature == null) {
return;
}
+ if (signature.equals(
+ "<R::Lcom/android/tools/r8/synthesis/Rewritable<TR;>;>Ljava/lang/Object;")) {
+ int xyz = 0;
+ }
TestDiagnosticMessagesImpl testDiagnosticMessages = new TestDiagnosticMessagesImpl();
ClassSignature classSignature =
GenericSignature.parseClassSignature(
diff --git a/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureCorrectnessHelperTests.java b/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureCorrectnessHelperTests.java
index 65b434b..969a59f 100644
--- a/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureCorrectnessHelperTests.java
+++ b/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureCorrectnessHelperTests.java
@@ -14,6 +14,7 @@
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.GenericSignatureContextBuilder;
import com.android.tools.r8.graph.GenericSignatureCorrectnessHelper;
import com.android.tools.r8.graph.GenericSignatureCorrectnessHelper.SignatureEvaluationResult;
import com.android.tools.r8.transformers.ClassFileTransformer.MethodPredicate;
@@ -44,9 +45,10 @@
buildInnerClasses(GenericSignatureCorrectnessHelperTests.class)
.addLibraryFile(ToolHelper.getJava8RuntimeJar())
.build());
- GenericSignatureCorrectnessHelper check =
- GenericSignatureCorrectnessHelper.createForVerification(appView);
- check.run();
+ GenericSignatureContextBuilder contextBuilder =
+ GenericSignatureContextBuilder.create(appView.appInfo().classes());
+ GenericSignatureCorrectnessHelper.createForVerification(appView, contextBuilder)
+ .run(appView.appInfo().classes());
}
@Test
@@ -139,7 +141,7 @@
})
.transform()),
ClassWithInvalidArgumentCount.class,
- SignatureEvaluationResult.INVALID_APPLICATION_COUNT);
+ SignatureEvaluationResult.VALID);
}
@Test
@@ -182,8 +184,10 @@
.addClassProgramData(transformations)
.addLibraryFile(ToolHelper.getJava8RuntimeJar())
.build());
+ GenericSignatureContextBuilder contextBuilder =
+ GenericSignatureContextBuilder.create(appView.appInfo().classes());
GenericSignatureCorrectnessHelper check =
- GenericSignatureCorrectnessHelper.createForInitialCheck(appView);
+ GenericSignatureCorrectnessHelper.createForInitialCheck(appView, contextBuilder);
DexProgramClass clazz =
appView
.definitionFor(
diff --git a/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignaturePartialTypeArgumentApplierTest.java b/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignaturePartialTypeArgumentApplierTest.java
index 64f2ac3..1fb82ab 100644
--- a/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignaturePartialTypeArgumentApplierTest.java
+++ b/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignaturePartialTypeArgumentApplierTest.java
@@ -13,12 +13,16 @@
import com.android.tools.r8.TestDiagnosticMessagesImpl;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GenericSignature;
import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
+import com.android.tools.r8.graph.GenericSignatureContextBuilder.TypeParameterContext;
import com.android.tools.r8.graph.GenericSignaturePartialTypeArgumentApplier;
import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.BiPredicateUtils;
import com.google.common.collect.ImmutableMap;
import java.util.Collections;
@@ -48,7 +52,7 @@
}
@Test
- public void testVariablesInOuterPosition() {
+ public void testVariablesInOuterPosition() throws Exception {
runTest(
ImmutableMap.of("T", objectType, "R", objectType),
Collections.emptySet(),
@@ -60,7 +64,7 @@
}
@Test
- public void testVariablesInInnerPosition() {
+ public void testVariablesInInnerPosition() throws Exception {
runTest(
ImmutableMap.of("T", objectType, "R", objectType),
Collections.emptySet(),
@@ -72,7 +76,7 @@
}
@Test
- public void testRemovingPrunedLink() {
+ public void testRemovingPrunedLink() throws Exception {
runTest(
Collections.emptyMap(),
Collections.emptySet(),
@@ -85,7 +89,7 @@
}
@Test
- public void testRemovedGenericArguments() {
+ public void testRemovedGenericArguments() throws Exception {
runTest(
Collections.emptyMap(),
Collections.emptySet(),
@@ -102,11 +106,17 @@
BiPredicate<DexType, DexType> removedLink,
Predicate<DexType> hasFormalTypeParameters,
String initialSignature,
- String expectedRewrittenSignature) {
+ String expectedRewrittenSignature)
+ throws Exception {
+ AppView<AppInfo> appView = computeAppView(AndroidApp.builder().build());
GenericSignaturePartialTypeArgumentApplier argumentApplier =
GenericSignaturePartialTypeArgumentApplier.build(
- objectType, removedLink, hasFormalTypeParameters)
- .addSubstitutionsAndVariables(substitutions, liveVariables);
+ appView,
+ TypeParameterContext.empty()
+ .addPrunedSubstitutions(substitutions)
+ .addLiveParameters(liveVariables),
+ removedLink,
+ hasFormalTypeParameters);
TestDiagnosticMessagesImpl diagnosticsHandler = new TestDiagnosticMessagesImpl();
MethodTypeSignature methodTypeSignature =
argumentApplier.visitMethodSignature(
diff --git a/src/test/java/com/android/tools/r8/graph/genericsignature/UnboundedFormalTypeGenericSignatureTest.java b/src/test/java/com/android/tools/r8/graph/genericsignature/UnboundedFormalTypeGenericSignatureTest.java
index 58812ee..80939de 100644
--- a/src/test/java/com/android/tools/r8/graph/genericsignature/UnboundedFormalTypeGenericSignatureTest.java
+++ b/src/test/java/com/android/tools/r8/graph/genericsignature/UnboundedFormalTypeGenericSignatureTest.java
@@ -6,7 +6,6 @@
import static org.hamcrest.CoreMatchers.containsString;
-import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
@@ -87,53 +86,51 @@
@Test
public void testUnboundParametersInClassR8() throws Exception {
- R8TestRunResult runResult =
- testForR8(parameters.getBackend())
- .addProgramClassFileData(
- transformer(Main.class)
- .removeInnerClasses()
- .setGenericSignature("L" + SUPER_BINARY_NAME + "<TR;>;")
- .transform(),
- transformer(Super.class).removeInnerClasses().transform())
- .addKeepAllClassesRule()
- .addKeepAttributes(
- ProguardKeepAttributes.SIGNATURE,
- ProguardKeepAttributes.INNER_CLASSES,
- ProguardKeepAttributes.ENCLOSING_METHOD)
- .setMinApi(parameters.getApiLevel())
- .run(parameters.getRuntime(), Main.class);
- if (parameters.isCfRuntime()) {
- runResult.assertFailureWithErrorThatMatches(containsString("java.lang.NullPointerException"));
- } else {
- runResult.assertSuccessWithOutputLines(Super.class.getTypeName() + "<R>", "R", "T");
- }
+ testForR8(parameters.getBackend())
+ .addProgramClassFileData(
+ transformer(Main.class)
+ .removeInnerClasses()
+ .setGenericSignature("L" + SUPER_BINARY_NAME + "<TR;>;")
+ .transform(),
+ transformer(Super.class).removeInnerClasses().transform())
+ .addKeepAllClassesRule()
+ .addKeepAttributes(
+ ProguardKeepAttributes.SIGNATURE,
+ ProguardKeepAttributes.INNER_CLASSES,
+ ProguardKeepAttributes.ENCLOSING_METHOD)
+ .setMinApi(parameters.getApiLevel())
+ .allowDiagnosticInfoMessages()
+ .compile()
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(
+ "class " + Super.class.getTypeName(), "R", "class java.lang.Object");
}
@Test
public void testUnboundParametersInMethodR8() throws Exception {
- R8TestRunResult runResult =
- testForR8(parameters.getBackend())
- .addProgramClassFileData(
- transformer(Main.class)
- .removeInnerClasses()
- .setGenericSignature(
- MethodPredicate.onName("testStatic"), "<R:Ljava/lang/Object;>()TS;")
- .setGenericSignature(
- MethodPredicate.onName("testVirtual"), "<R:Ljava/lang/Object;>()TQ;")
- .transform(),
- transformer(Super.class).removeInnerClasses().transform())
- .addKeepAllClassesRule()
- .addKeepAttributes(
- ProguardKeepAttributes.SIGNATURE,
- ProguardKeepAttributes.INNER_CLASSES,
- ProguardKeepAttributes.ENCLOSING_METHOD)
- .setMinApi(parameters.getApiLevel())
- .run(parameters.getRuntime(), Main.class);
- if (parameters.isCfRuntime()) {
- runResult.assertSuccessWithOutputLines(Super.class.getTypeName() + "<T>", "null", "null");
- } else {
- runResult.assertSuccessWithOutputLines(Super.class.getTypeName() + "<T>", "S", "Q");
- }
+ testForR8(parameters.getBackend())
+ .addProgramClassFileData(
+ transformer(Main.class)
+ .removeInnerClasses()
+ .setGenericSignature(
+ MethodPredicate.onName("testStatic"), "<R:Ljava/lang/Object;>()TS;")
+ .setGenericSignature(
+ MethodPredicate.onName("testVirtual"), "<R:Ljava/lang/Object;>()TQ;")
+ .transform(),
+ transformer(Super.class).removeInnerClasses().transform())
+ .addKeepAllClassesRule()
+ .addKeepAttributes(
+ ProguardKeepAttributes.SIGNATURE,
+ ProguardKeepAttributes.INNER_CLASSES,
+ ProguardKeepAttributes.ENCLOSING_METHOD)
+ .setMinApi(parameters.getApiLevel())
+ .allowDiagnosticInfoMessages()
+ .compile()
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(
+ Super.class.getTypeName() + "<T>", "class java.lang.Object", "class java.lang.Object");
}
public static class Super<T> {}
diff --git a/src/test/java/com/android/tools/r8/graph/genericsignature/UnknownClassInSignatureTest.java b/src/test/java/com/android/tools/r8/graph/genericsignature/UnknownClassInSignatureTest.java
index 4c2ac5e..cf67f18 100644
--- a/src/test/java/com/android/tools/r8/graph/genericsignature/UnknownClassInSignatureTest.java
+++ b/src/test/java/com/android/tools/r8/graph/genericsignature/UnknownClassInSignatureTest.java
@@ -7,6 +7,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
@@ -27,7 +28,6 @@
public class UnknownClassInSignatureTest extends TestBase {
private final TestParameters parameters;
- private final String NEW_CLASS_SIGNATURE = "<T:LUnknownClass1;>LUnknownClass2<LUnknownClass3;>;";
private final String NEW_FIELD_SIGNATURE = "LUnknownClass4<LUnknownClass4;>;";
private final String NEW_METHOD_SIGNATURE = "()LUnkownClass5<LunknownPackage/UnknownClass6;>;";
@@ -46,7 +46,7 @@
.addProgramClassFileData(
transformer(Main.class)
.removeInnerClasses()
- .setGenericSignature(NEW_CLASS_SIGNATURE)
+ .setGenericSignature("<T:LUnknownClass1;>LUnknownClass2<LUnknownClass3;>;")
.setGenericSignature(FieldPredicate.onName("field"), NEW_FIELD_SIGNATURE)
.setGenericSignature(MethodPredicate.onName("main"), NEW_METHOD_SIGNATURE)
.transform())
@@ -56,13 +56,16 @@
ProguardKeepAttributes.ENCLOSING_METHOD,
ProguardKeepAttributes.INNER_CLASSES)
.setMinApi(parameters.getApiLevel())
+ .allowDiagnosticInfoMessages()
+ .compile()
+ .apply(TestBase::verifyExpectedInfoFromGenericSignatureSuperTypeValidation)
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("Hello World!")
.inspect(
inspector -> {
ClassSubject clazz = inspector.clazz(Main.class);
assertThat(clazz, isPresent());
- assertEquals(NEW_CLASS_SIGNATURE, clazz.getFinalSignatureAttribute());
+ assertNull(clazz.getFinalSignatureAttribute());
FieldSubject field = clazz.uniqueFieldWithFinalName("field");
assertThat(field, isPresent());
assertEquals(NEW_FIELD_SIGNATURE, field.getFinalSignatureAttribute());
diff --git a/src/test/java/com/android/tools/r8/internal/ClankDepsTest.java b/src/test/java/com/android/tools/r8/internal/ClankDepsTest.java
index 82570e9..00fff76 100644
--- a/src/test/java/com/android/tools/r8/internal/ClankDepsTest.java
+++ b/src/test/java/com/android/tools/r8/internal/ClankDepsTest.java
@@ -45,6 +45,8 @@
.allowUnusedProguardConfigurationRules()
.allowUnnecessaryDontWarnWildcards()
.setMinApi(AndroidApiLevel.N)
- .compileWithExpectedDiagnostics(TestDiagnosticMessages::assertOnlyInfos);
+ .allowDiagnosticInfoMessages()
+ .compileWithExpectedDiagnostics(TestDiagnosticMessages::assertOnlyInfos)
+ .apply(TestBase::verifyHasInfoFromGenericSignatureTypeParameterValidation);
}
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinReflectionLibTest.java b/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinReflectionLibTest.java
index 548ce4d..049974c 100644
--- a/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinReflectionLibTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/ProcessKotlinReflectionLibTest.java
@@ -100,12 +100,20 @@
@Test
public void testDontOptimize() throws Exception {
- test(TestShrinkerBuilder::noOptimization);
+ test(
+ builder -> {
+ builder.allowDiagnosticInfoMessages();
+ builder.noOptimization();
+ });
}
@Test
public void testDontObfuscate() throws Exception {
- test(TestShrinkerBuilder::noMinification);
+ test(
+ builder -> {
+ builder.allowDiagnosticInfoMessages();
+ builder.noMinification();
+ });
}
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataStripTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataStripTest.java
index 6406593..ca441cd 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataStripTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataStripTest.java
@@ -14,6 +14,7 @@
import com.android.tools.r8.KotlinTestParameters;
import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
import com.android.tools.r8.utils.codeinspector.AnnotationSubject;
@@ -58,10 +59,12 @@
.addKeepMainRule(mainClassName)
.addKeepKotlinMetadata()
.addKeepAttributes(ProguardKeepAttributes.RUNTIME_VISIBLE_ANNOTATIONS)
- .allowDiagnosticWarningMessages()
+ .allowDiagnosticMessages()
.setMinApi(parameters.getApiLevel())
.allowUnusedDontWarnKotlinReflectJvmInternal(kotlinc.isNot(KOTLINC_1_3_72))
.compile()
+ .assertNoErrorMessages()
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation)
.apply(KotlinMetadataTestBase::verifyExpectedWarningsFromKotlinReflectAndStdLib)
.run(parameters.getRuntime(), mainClassName);
CodeInspector inspector = result.inspector();
diff --git a/src/test/java/com/android/tools/r8/kotlin/optimize/switches/KotlinEnumSwitchTest.java b/src/test/java/com/android/tools/r8/kotlin/optimize/switches/KotlinEnumSwitchTest.java
index 9c01d63..8a27b3f 100644
--- a/src/test/java/com/android/tools/r8/kotlin/optimize/switches/KotlinEnumSwitchTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/optimize/switches/KotlinEnumSwitchTest.java
@@ -11,8 +11,12 @@
import static org.junit.Assert.assertNotEquals;
import com.android.tools.r8.KotlinCompilerTool;
+import com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion;
import com.android.tools.r8.KotlinTestBase;
import com.android.tools.r8.KotlinTestParameters;
+import com.android.tools.r8.R8TestBuilder;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestCompileResult;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -60,10 +64,18 @@
options.enableEnumValueOptimization = enableSwitchMapRemoval;
options.enableEnumSwitchMapRemoval = enableSwitchMapRemoval;
})
- .allowDiagnosticWarningMessages()
+ .applyIf(
+ kotlinParameters.getCompiler().is(KotlinCompilerVersion.KOTLINC_1_5_0_M2),
+ R8TestBuilder::allowDiagnosticMessages,
+ R8TestBuilder::allowDiagnosticWarningMessages)
.setMinApi(parameters.getApiLevel())
.noMinification()
.compile()
+ .assertNoErrorMessages()
+ .applyIf(
+ kotlinParameters.getCompiler().is(KotlinCompilerVersion.KOTLINC_1_5_0_M2),
+ TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation,
+ TestCompileResult::assertNoInfoMessages)
.assertAllWarningMessagesMatch(equalTo("Resource 'META-INF/MANIFEST.MF' already exists."))
.inspect(
inspector -> {
diff --git a/src/test/java/com/android/tools/r8/kotlin/reflection/KotlinReflectTest.java b/src/test/java/com/android/tools/r8/kotlin/reflection/KotlinReflectTest.java
index 4e376ed..6ee2517 100644
--- a/src/test/java/com/android/tools/r8/kotlin/reflection/KotlinReflectTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/reflection/KotlinReflectTest.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.DexIndexedConsumer.ArchiveConsumer;
import com.android.tools.r8.KotlinTestBase;
import com.android.tools.r8.KotlinTestParameters;
+import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.kotlin.metadata.KotlinMetadataTestBase;
@@ -91,11 +92,13 @@
.setMinApi(parameters.getApiLevel())
.addKeepAllClassesRule()
.addKeepAttributes(ProguardKeepAttributes.RUNTIME_VISIBLE_ANNOTATIONS)
- .allowDiagnosticWarningMessages()
+ .allowDiagnosticMessages()
.allowUnusedDontWarnKotlinReflectJvmInternal(kotlinc.isNot(KOTLINC_1_3_72))
.compile()
- .writeToZip(foo.toPath())
+ .assertNoErrorMessages()
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation)
.apply(KotlinMetadataTestBase::verifyExpectedWarningsFromKotlinReflectAndStdLib)
+ .writeToZip(foo.toPath())
.run(parameters.getRuntime(), PKG + ".SimpleReflectKt")
.assertSuccessWithOutputLines(EXPECTED_OUTPUT);
}
diff --git a/src/test/java/com/android/tools/r8/naming/MinifierClassSignatureTest.java b/src/test/java/com/android/tools/r8/naming/MinifierClassSignatureTest.java
index dc3acee..0aa7a87 100644
--- a/src/test/java/com/android/tools/r8/naming/MinifierClassSignatureTest.java
+++ b/src/test/java/com/android/tools/r8/naming/MinifierClassSignatureTest.java
@@ -330,7 +330,6 @@
internalOptions.testing.disableMappingToOriginalProgramVerification = true)
.compile();
- compileResult.assertNoInfoMessages();
compileResult.assertNoErrorMessages();
CodeInspector inspector = compileResult.inspector();
@@ -415,28 +414,6 @@
}
@Test
- public void classSignatureOuter_valid() throws Exception {
- // class Outer<T extends Simple> extends Base<T>
- String signature = "<T:LSimple;>LBase<TT;>;";
- testSingleClass(
- "Outer",
- signature,
- TestDiagnosticMessages::assertNoWarnings,
- inspector -> {
- ClassSubject outer = inspector.clazz("Outer");
- ClassSubject simple = inspector.clazz("Simple");
- ClassSubject base = inspector.clazz("Base");
- String baseDescriptorWithoutSemicolon =
- base.getFinalDescriptor().substring(0, base.getFinalDescriptor().length() - 1);
- String minifiedSignature =
- "<T:" + simple.getFinalDescriptor() + ">" + baseDescriptorWithoutSemicolon + "<TT;>;";
- assertEquals(minifiedSignature, outer.getFinalSignatureAttribute());
- assertEquals(signature, outer.getOriginalSignatureAttribute());
- },
- false);
- }
-
- @Test
public void classSignatureExtendsInner_valid() throws Exception {
String signature = "LOuter<TT;>.Inner;";
testSingleClass(
@@ -469,9 +446,9 @@
inspector -> {
assertThat(inspector.clazz("NotFound"), not(isPresent()));
ClassSubject outer = inspector.clazz("Outer");
- assertEquals(signature, outer.getOriginalSignatureAttribute());
+ assertNull(outer.getOriginalSignatureAttribute());
},
- false);
+ true);
}
@Test
@@ -484,8 +461,8 @@
inspector -> {
assertThat(inspector.clazz("NotFound"), not(isPresent()));
ClassSubject outer = inspector.clazz("Outer$ExtendsInner");
- // TODO(b/1867459990): What to do here.
- assertEquals("LOuter$NotFound;", outer.getOriginalSignatureAttribute());
+ // TODO(b/186745999): What to do here.
+ assertNull(outer.getOriginalSignatureAttribute());
},
false);
}
@@ -500,7 +477,7 @@
inspector -> {
assertThat(inspector.clazz("NotFound"), not(isPresent()));
ClassSubject outer = inspector.clazz("Outer$ExtendsInner");
- assertEquals(signature, outer.getOriginalSignatureAttribute());
+ assertNull(outer.getOriginalSignatureAttribute());
},
false);
}
@@ -516,13 +493,13 @@
assertThat(inspector.clazz("NotFound"), not(isPresent()));
ClassSubject outer = inspector.clazz("Outer$ExtendsInner");
// TODO(b/1867459990): What to do here.
- assertEquals("LOuter$Inner$NotFound;", outer.getOriginalSignatureAttribute());
+ assertNull(outer.getOriginalSignatureAttribute());
},
false);
}
@Test
- public void classSignatureExtendsInner_multipleMestedInnerClassesNotFound() throws Exception {
+ public void classSignatureExtendsInner_multipleNestedInnerClassesNotFound() throws Exception {
String signature = "LOuter<TT;>.NotFound.AlsoNotFound;";
testSingleClass(
"Outer$ExtendsInner",
@@ -531,8 +508,7 @@
inspector -> {
assertThat(inspector.clazz("NotFound"), not(isPresent()));
ClassSubject outer = inspector.clazz("Outer$ExtendsInner");
- // TODO(b/1867459990): What to do here.
- assertEquals("LOuter$NotFound$AlsoNotFound;", outer.getOriginalSignatureAttribute());
+ assertNull(outer.getOriginalSignatureAttribute());
},
false);
}
diff --git a/src/test/java/com/android/tools/r8/shaking/KeepAnnotatedMemberTest.java b/src/test/java/com/android/tools/r8/shaking/KeepAnnotatedMemberTest.java
index 550356e..a7b7bfd 100644
--- a/src/test/java/com/android/tools/r8/shaking/KeepAnnotatedMemberTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/KeepAnnotatedMemberTest.java
@@ -77,9 +77,10 @@
.addDontWarnGoogle()
.addDontWarnJavax()
.addDontWarn("org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement")
+ .allowDiagnosticInfoMessages()
.compileWithExpectedDiagnostics(
- diagnostics ->
- diagnostics.assertErrorsMatch(diagnosticException(AssertionError.class)));
+ diagnostics -> diagnostics.assertErrorsMatch(diagnosticException(AssertionError.class)))
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation);
}
@Test
@@ -92,7 +93,9 @@
.addDontWarnGoogle()
.addDontWarnJavax()
.addDontWarn("org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement")
- .compile();
+ .allowDiagnosticInfoMessages()
+ .compile()
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation);
}
@Test
@@ -101,7 +104,9 @@
.addProgramFiles(R8_JAR)
.allowUnusedProguardConfigurationRules()
.addKeepRules("-keepclasseswithmembers class * { @" + ABSENT_ANNOTATION + " *; }")
+ .allowDiagnosticInfoMessages()
.compile()
+ .apply(TestBase::verifyHasInfoFromGenericSignatureTypeParameterValidation)
.inspect(inspector -> assertEquals(0, inspector.allClasses().size()));
}
@@ -113,7 +118,9 @@
.addDontWarnGoogle()
.addDontWarnJavax()
.addDontWarn("org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement")
+ .allowDiagnosticInfoMessages()
.compile()
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation)
.inspect(
inspector -> {
ClassSubject clazz = inspector.clazz(CLASS_WITH_ANNOTATED_METHOD);
@@ -129,7 +136,9 @@
// TODO(b/159971974): Technically this rule does not hit anything and should fail due to
// missing allowUnusedProguardConfigurationRules()
.addKeepRules("-keepclassmembers class * { @" + PRESENT_ANNOTATION + " *** *(...); }")
+ .allowDiagnosticInfoMessages()
.compile()
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation)
.inspect(inspector -> assertEquals(0, inspector.allClasses().size()));
}
@@ -139,7 +148,9 @@
.addProgramFiles(R8_JAR)
.addKeepClassRules(CLASS_WITH_ANNOTATED_METHOD)
.addKeepRules("-keepclassmembers class * { @" + PRESENT_ANNOTATION + " *** *(...); }")
+ .allowDiagnosticInfoMessages()
.compile()
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation)
.inspect(
inspector -> {
assertEquals(1, inspector.allClasses().size());
@@ -162,7 +173,9 @@
.addProgramFiles(R8_JAR)
.allowUnusedProguardConfigurationRules()
.addKeepRules("-if class * -keep class <1> { @" + PRESENT_ANNOTATION + " *** *(...); }")
+ .allowDiagnosticInfoMessages()
.compile()
+ .apply(TestBase::verifyHasInfoFromGenericSignatureTypeParameterValidation)
.inspect(inspector -> assertEquals(0, inspector.allClasses().size()));
}
@@ -172,7 +185,9 @@
.addProgramFiles(R8_JAR)
.addKeepClassRules(CLASS_WITH_ANNOTATED_METHOD)
.addKeepRules("-if class * -keep class <1> { @" + PRESENT_ANNOTATION + " *** *(...); }")
+ .allowDiagnosticInfoMessages()
.compile()
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation)
.inspect(
inspector -> {
assertEquals(1, inspector.allClasses().size());
@@ -204,7 +219,9 @@
.addKeepRules("-keepclassmembers class * { @" + PRESENT_ANNOTATION + " *** *(...); }")
.addDontWarnGoogle()
.addDontWarnJavaxNullableAnnotation()
+ .allowDiagnosticInfoMessages()
.compile()
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation)
.graphInspector();
GraphInspector ifThenKeepClassMembersInspector =
@@ -222,7 +239,9 @@
+ " *** *(...); }")
.addDontWarnGoogle()
.addDontWarnJavaxNullableAnnotation()
+ .allowDiagnosticInfoMessages()
.compile()
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation)
.graphInspector();
assertRetainedClassesEqual(referenceInspector, ifThenKeepClassMembersInspector);
@@ -241,7 +260,9 @@
+ " *** *(...); }")
.addDontWarnGoogle()
.addDontWarnJavaxNullableAnnotation()
+ .allowDiagnosticInfoMessages()
.compile()
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation)
.graphInspector();
assertRetainedClassesEqual(referenceInspector, ifThenKeepClassesWithMembersInspector);
@@ -262,7 +283,9 @@
+ " *** <2>(...); }")
.addDontWarnGoogle()
.addDontWarnJavaxNullableAnnotation()
+ .allowDiagnosticInfoMessages()
.compile()
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation)
.graphInspector();
assertRetainedClassesEqual(referenceInspector, ifHasMemberThenKeepClassInspector);
}
diff --git a/src/test/java/com/android/tools/r8/shaking/keptgraph/WhyAreYouKeepingAllTest.java b/src/test/java/com/android/tools/r8/shaking/keptgraph/WhyAreYouKeepingAllTest.java
index 94bdbf1..ac22ab7 100644
--- a/src/test/java/com/android/tools/r8/shaking/keptgraph/WhyAreYouKeepingAllTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/keptgraph/WhyAreYouKeepingAllTest.java
@@ -48,7 +48,9 @@
.addKeepRuleFiles(MAIN_KEEP)
.addKeepRules(WHY_ARE_YOU_KEEPING_ALL)
.collectStdout()
+ .allowDiagnosticInfoMessages()
.compile()
+ .apply(TestBase::verifyAllInfoFromGenericSignatureTypeParameterValidation)
.assertStdoutThatMatches(containsString("referenced in keep rule"))
// TODO(b/124655065): We should always know the reason for keeping.
// It is OK if this starts failing while the kept-graph API is incomplete, in which case