Introduce keepinfo for signature removal
This CL will also allow R8 in full mode to strip generic signatures for classes that are not kept when having -dontoptimize
Bug: 221404266
Bug: 190469643
Change-Id: I9c008b5e46b424ace805d738b646bd3980ace639
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 950e824..7864ee8 100644
--- a/src/main/java/com/android/tools/r8/graph/GenericSignatureCorrectnessHelper.java
+++ b/src/main/java/com/android/tools/r8/graph/GenericSignatureCorrectnessHelper.java
@@ -139,7 +139,7 @@
KeepClassInfo classInfo = appView.getKeepInfo().getClassInfo(clazz);
if (appView.hasLiveness() && !classInfo.isShrinkingAllowed(appView.options())) {
// If/when this no longer holds it should be moved into the condition.
- assert !classInfo.isSignatureAttributeRemovalAllowed(appView.options());
+ assert !classInfo.isSignatureRemovalAllowed(appView.options());
appView
.options()
.reporter
@@ -167,7 +167,7 @@
if (appView.hasLiveness()
&& !methodInfo.isShrinkingAllowed(appView.options())) {
// If/when this no longer holds it should be moved into the condition.
- assert !methodInfo.isSignatureAttributeRemovalAllowed(appView.options());
+ assert !methodInfo.isSignatureRemovalAllowed(appView.options());
appView
.options()
.reporter
@@ -195,7 +195,7 @@
// ensure we do not spam the developer with messages they can do nothing about.
if (appView.hasLiveness() && !fieldInfo.isShrinkingAllowed(appView.options())) {
// If/when this no longer holds it should be moved into the condition.
- assert !fieldInfo.isSignatureAttributeRemovalAllowed(appView.options());
+ assert !fieldInfo.isSignatureRemovalAllowed(appView.options());
appView
.options()
.reporter
diff --git a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
index 1b2e03c..4b9385d 100644
--- a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
@@ -217,7 +217,7 @@
Set<KotlinPropertyInfo> pinnedKotlinProperties) {
KeepMemberInfo<?, ?> memberInfo = appView.getKeepInfo().getMemberInfo(member);
removeAnnotations(member, memberInfo);
- if (memberInfo.isSignatureAttributeRemovalAllowed(options)) {
+ if (memberInfo.isSignatureRemovalAllowed(options)) {
member.clearGenericSignature();
}
if (!member.getKotlinInfo().isProperty()
@@ -346,8 +346,7 @@
clazz.removeInnerClasses(
attribute ->
canRemoveInnerClassAttribute(clazz, attribute, clazz.getEnclosingMethodAttribute()));
- if (clazz.getClassSignature().isValid()
- && keepInfo.isSignatureAttributeRemovalAllowed(options)) {
+ if (clazz.getClassSignature().isValid() && keepInfo.isSignatureRemovalAllowed(options)) {
clazz.clearClassSignature();
}
}
diff --git a/src/main/java/com/android/tools/r8/shaking/KeepInfo.java b/src/main/java/com/android/tools/r8/shaking/KeepInfo.java
index bcf9467..713633b 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepInfo.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepInfo.java
@@ -21,6 +21,7 @@
private final boolean allowMinification;
private final boolean allowOptimization;
private final boolean allowShrinking;
+ private final boolean allowSignatureRemoval;
private final boolean checkDiscarded;
private final boolean requireAccessModificationForRepackaging;
@@ -30,6 +31,7 @@
boolean allowMinification,
boolean allowOptimization,
boolean allowShrinking,
+ boolean allowSignatureRemoval,
boolean checkDiscarded,
boolean requireAccessModificationForRepackaging) {
this.allowAccessModification = allowAccessModification;
@@ -37,6 +39,7 @@
this.allowMinification = allowMinification;
this.allowOptimization = allowOptimization;
this.allowShrinking = allowShrinking;
+ this.allowSignatureRemoval = allowSignatureRemoval;
this.checkDiscarded = checkDiscarded;
this.requireAccessModificationForRepackaging = requireAccessModificationForRepackaging;
}
@@ -48,6 +51,7 @@
builder.isMinificationAllowed(),
builder.isOptimizationAllowed(),
builder.isShrinkingAllowed(),
+ builder.isSignatureRemovalAllowed(),
builder.isCheckDiscardedEnabled(),
builder.isAccessModificationRequiredForRepackaging());
}
@@ -136,6 +140,24 @@
}
/**
+ * True if an item may have its generic signature removed.
+ *
+ * <p>This method requires knowledge of the global configuration as that can override the concrete
+ * value on a given item.
+ */
+ public boolean isSignatureRemovalAllowed(GlobalKeepInfoConfiguration configuration) {
+ if (!configuration.isKeepAttributesSignatureEnabled()) {
+ return true;
+ }
+ return !configuration.isForceProguardCompatibilityEnabled()
+ && internalIsSignatureRemovalAllowed();
+ }
+
+ boolean internalIsSignatureRemovalAllowed() {
+ return allowSignatureRemoval;
+ }
+
+ /**
* True if an item may be repackaged.
*
* <p>This method requires knowledge of the global configuration as that can override the concrete
@@ -165,13 +187,6 @@
return allowAccessModification;
}
- public boolean isSignatureAttributeRemovalAllowed(GlobalKeepInfoConfiguration configuration) {
- if (!configuration.isKeepAttributesSignatureEnabled()) {
- return true;
- }
- return !(configuration.isForceProguardCompatibilityEnabled() || isPinned(configuration));
- }
-
public boolean isEnclosingMethodAttributeRemovalAllowed(
GlobalKeepInfoConfiguration configuration,
EnclosingMethodAttribute enclosingMethodAttribute,
@@ -218,6 +233,7 @@
&& (allowMinification || !other.internalIsMinificationAllowed())
&& (allowOptimization || !other.internalIsOptimizationAllowed())
&& (allowShrinking || !other.internalIsShrinkingAllowed())
+ && (allowSignatureRemoval || !other.internalIsSignatureRemovalAllowed())
&& (!checkDiscarded || other.internalIsCheckDiscardedEnabled());
}
@@ -240,6 +256,7 @@
private boolean allowMinification;
private boolean allowOptimization;
private boolean allowShrinking;
+ private boolean allowSignatureRemoval;
private boolean checkDiscarded;
private boolean requireAccessModificationForRepackaging;
@@ -254,6 +271,7 @@
allowMinification = original.internalIsMinificationAllowed();
allowOptimization = original.internalIsOptimizationAllowed();
allowShrinking = original.internalIsShrinkingAllowed();
+ allowSignatureRemoval = original.internalIsSignatureRemovalAllowed();
checkDiscarded = original.internalIsCheckDiscardedEnabled();
requireAccessModificationForRepackaging =
original.internalIsAccessModificationRequiredForRepackaging();
@@ -265,6 +283,7 @@
disallowMinification();
disallowOptimization();
disallowShrinking();
+ disallowSignatureRemoval();
unsetCheckDiscarded();
requireAccessModificationForRepackaging();
return self();
@@ -276,6 +295,7 @@
allowMinification();
allowOptimization();
allowShrinking();
+ allowSignatureRemoval();
unsetCheckDiscarded();
unsetRequireAccessModificationForRepackaging();
return self();
@@ -302,6 +322,7 @@
&& isMinificationAllowed() == other.internalIsMinificationAllowed()
&& isOptimizationAllowed() == other.internalIsOptimizationAllowed()
&& isShrinkingAllowed() == other.internalIsShrinkingAllowed()
+ && isSignatureRemovalAllowed() == other.internalIsSignatureRemovalAllowed()
&& isCheckDiscardedEnabled() == other.internalIsCheckDiscardedEnabled()
&& isAccessModificationRequiredForRepackaging()
== other.internalIsAccessModificationRequiredForRepackaging();
@@ -335,6 +356,10 @@
return allowShrinking;
}
+ public boolean isSignatureRemovalAllowed() {
+ return allowSignatureRemoval;
+ }
+
public B setAllowMinification(boolean allowMinification) {
this.allowMinification = allowMinification;
return self();
@@ -426,6 +451,19 @@
public B disallowAnnotationRemoval() {
return setAllowAnnotationRemoval(false);
}
+
+ private B setAllowSignatureRemoval(boolean allowSignatureRemoval) {
+ this.allowSignatureRemoval = allowSignatureRemoval;
+ return self();
+ }
+
+ public B allowSignatureRemoval() {
+ return setAllowSignatureRemoval(true);
+ }
+
+ public B disallowSignatureRemoval() {
+ return setAllowSignatureRemoval(false);
+ }
}
/** Joiner to construct monotonically increasing keep info object. */
@@ -519,6 +557,11 @@
return self();
}
+ public J disallowSignatureRemoval() {
+ builder.disallowSignatureRemoval();
+ return self();
+ }
+
public J setCheckDiscarded() {
builder.setCheckDiscarded();
return self();
@@ -536,6 +579,7 @@
applyIf(!builder.isMinificationAllowed(), Joiner::disallowMinification);
applyIf(!builder.isOptimizationAllowed(), Joiner::disallowOptimization);
applyIf(!builder.isShrinkingAllowed(), Joiner::disallowShrinking);
+ applyIf(!builder.isSignatureRemovalAllowed(), Joiner::disallowSignatureRemoval);
applyIf(builder.isCheckDiscardedEnabled(), Joiner::setCheckDiscarded);
applyIf(
builder.isAccessModificationRequiredForRepackaging(),
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
index 524fe08..b10e649 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
@@ -1532,6 +1532,13 @@
context.markAsUsed();
}
+ if (appView.options().isKeepAttributesSignatureEnabled()) {
+ dependentMinimumKeepInfo
+ .getOrCreateMinimumKeepInfoFor(preconditionEvent, item.getReference())
+ .disallowSignatureRemoval();
+ context.markAsUsed();
+ }
+
if (appView.options().isMinificationEnabled() && !modifiers.allowsObfuscation) {
dependentMinimumKeepInfo
.getOrCreateMinimumKeepInfoFor(preconditionEvent, item.getReference())
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 7db2e06..12e0a78 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -636,12 +636,12 @@
}
public boolean parseSignatureAttribute() {
- return proguardConfiguration == null || isKeepAttributesSignatureEnabled();
+ return isKeepAttributesSignatureEnabled();
}
@Override
public boolean isKeepAttributesSignatureEnabled() {
- return proguardConfiguration.getKeepAttributes().signature;
+ return proguardConfiguration == null || proguardConfiguration.getKeepAttributes().signature;
}
@Override
diff --git a/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureDontOptimizeTest.java b/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureDontOptimizeTest.java
index 7c55472..94adea2 100644
--- a/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureDontOptimizeTest.java
+++ b/src/test/java/com/android/tools/r8/graph/genericsignature/GenericSignatureDontOptimizeTest.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;
@@ -45,11 +46,10 @@
.addKeepClassRules(Foo.class)
.addKeepMainRule(Main.class)
.addDontOptimize()
- .run(parameters.getRuntime(), Main.class)
+ .compile()
.inspect(this::inspect)
- // TODO(b/221404266): We should fail with an exception since the parameterized generic type
- // should be removed.
- .assertSuccessWithOutputLines(EXPECTED);
+ .run(parameters.getRuntime(), Main.class)
+ .assertFailureWithErrorThatThrows(ClassCastException.class);
}
private void inspect(CodeInspector inspector) {
@@ -57,11 +57,9 @@
assertThat(foo, isPresent());
assertEquals("<T:Ljava/lang/Object;>Ljava/lang/Object;", foo.getFinalSignatureAttribute());
- // TODO(b/221404266): We should not keep generic signatures when having -dontoptimize
ClassSubject main$1 = inspector.clazz(Main.class.getTypeName() + "$1");
assertThat(main$1, isPresent());
- assertEquals(
- "L" + binaryName(Foo.class) + "<Ljava/lang/String;>;", main$1.getFinalSignatureAttribute());
+ assertNull(main$1.getFinalSignatureAttribute());
}
public static class Foo<T> {