[KeepAnno] Support generic signature constraints
The KeepForApi is also updated to implicitly have the full constraint
set as its default. Doing so allows it to work for the expected cases of
compiling up against the annotated API.
Bug: b/248408342
Change-Id: I83cb3a35c801ba2f04ed892cc726d2d26a68e447
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/annotations/KeepConstraint.java b/src/keepanno/java/com/android/tools/r8/keepanno/annotations/KeepConstraint.java
index bd6f7c5..4a07562 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/annotations/KeepConstraint.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/annotations/KeepConstraint.java
@@ -209,4 +209,16 @@
* non-visible uses requires the same annotations to preserve as for reflective uses.
*/
CLASS_OPEN_HIERARCHY,
+
+ /**
+ * Indicates that the target item must retain its generic signature if present.
+ *
+ * <p>This ensures that the generic signature remains, but does not prohibit rewriting of the
+ * generic signature. For example, if a type present in the generic signature is renamed, the
+ * generic signature will also be updated to now refer to the type by its renamed name.
+ *
+ * <p>Note that this constraint does not otherwise restrict what can be done to the target, such
+ * as removing the target completely, inlining it, etc.
+ */
+ GENERIC_SIGNATURE,
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepConstraintsVisitor.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepConstraintsVisitor.java
index 33bf5be..a35f9e9 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepConstraintsVisitor.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepConstraintsVisitor.java
@@ -67,6 +67,9 @@
case Constraints.CLASS_OPEN_HIERARCHY:
builder.add(KeepConstraint.classOpenHierarchy());
break;
+ case Constraints.GENERIC_SIGNATURE:
+ builder.add(KeepConstraint.genericSignature());
+ break;
default:
super.visitEnum(ignore, descriptor, value);
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeReader.java b/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeReader.java
index b76ac2e..c6b6f64 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeReader.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/asm/KeepEdgeReader.java
@@ -960,6 +960,10 @@
v.visitEnum(null, MemberAccess.DESCRIPTOR, MemberAccess.PROTECTED);
}
super.visitEnd();
+ // Currently there is no way of changing constraints on KeepForApi.
+ // Default constraints should retain the expected meta-data, such as signatures, annotations
+ // exception-throws etc.
+ KeepConstraints defaultForApiConstraints = KeepConstraints.all();
Collection<KeepItemReference> items = getItemsWithoutBinding();
for (KeepItemReference item : items) {
if (item.isBindingReference()) {
@@ -981,7 +985,11 @@
if (!classItemPattern.getInstanceOfPattern().isAny()) {
throw parsingContext.error("cannot define an 'extends' pattern.");
}
- consequences.addTarget(KeepTarget.builder().setItemReference(item).build());
+ consequences.addTarget(
+ KeepTarget.builder()
+ .setItemReference(item)
+ .setConstraints(defaultForApiConstraints)
+ .build());
}
parent.accept(
builder
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/AnnotationConstants.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/AnnotationConstants.java
index 81ccbc6..0f85212 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/AnnotationConstants.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/AnnotationConstants.java
@@ -188,6 +188,7 @@
public static final String FIELD_REPLACE = "FIELD_REPLACE";
public static final String NEVER_INLINE = "NEVER_INLINE";
public static final String CLASS_OPEN_HIERARCHY = "CLASS_OPEN_HIERARCHY";
+ public static final String GENERIC_SIGNATURE = "GENERIC_SIGNATURE";
}
public static final class MemberAccess {
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepAttribute.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepAttribute.java
index 0e99854..17f9ece 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepAttribute.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepAttribute.java
@@ -5,6 +5,8 @@
package com.android.tools.r8.keepanno.ast;
public enum KeepAttribute {
+ GENERIC_SIGNATURES("Signature"),
+
RUNTIME_VISIBLE_ANNOTATIONS("RuntimeVisibleAnnotations"),
RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS("RuntimeVisibleParameterAnnotations"),
RUNTIME_VISIBLE_TYPE_ANNOTATIONS("RuntimeVisibleTypeAnnotations"),
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraint.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraint.java
index 5368d5e..2ae5f93 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraint.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraint.java
@@ -411,6 +411,37 @@
}
}
+ public static GenericSignature genericSignature() {
+ return GenericSignature.INSTANCE;
+ }
+
+ public static final class GenericSignature extends KeepConstraint {
+
+ private static final GenericSignature INSTANCE = new GenericSignature();
+
+ private GenericSignature() {}
+
+ @Override
+ public String getEnumValue() {
+ return Constraints.GENERIC_SIGNATURE;
+ }
+
+ @Override
+ public void accept(KeepConstraintVisitor visitor) {
+ visitor.onGenericSignature(this);
+ }
+
+ @Override
+ public void convertToDisallowKeepOptions(KeepOptions.Builder builder) {
+ builder.add(KeepOption.SIGNATURE_REMOVAL);
+ }
+
+ @Override
+ public void addRequiredKeepAttributes(Set<KeepAttribute> attributes) {
+ attributes.add(KeepAttribute.GENERIC_SIGNATURES);
+ }
+ }
+
public static Annotation annotationsAll() {
return Annotation.ALL_INSTANCE;
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraintVisitor.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraintVisitor.java
index f7db601..779dcc0 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraintVisitor.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraintVisitor.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.keepanno.ast.KeepConstraint.FieldGet;
import com.android.tools.r8.keepanno.ast.KeepConstraint.FieldReplace;
import com.android.tools.r8.keepanno.ast.KeepConstraint.FieldSet;
+import com.android.tools.r8.keepanno.ast.KeepConstraint.GenericSignature;
import com.android.tools.r8.keepanno.ast.KeepConstraint.Lookup;
import com.android.tools.r8.keepanno.ast.KeepConstraint.MethodInvoke;
import com.android.tools.r8.keepanno.ast.KeepConstraint.MethodReplace;
@@ -44,5 +45,7 @@
public abstract void onFieldReplace(FieldReplace constraint);
+ public abstract void onGenericSignature(GenericSignature constraint);
+
public abstract void onAnnotation(Annotation constraint);
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraints.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraints.java
index 12f10b0..6c55e6c 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraints.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepConstraints.java
@@ -16,6 +16,10 @@
public abstract class KeepConstraints {
+ public static KeepConstraints all() {
+ return All.INSTANCE;
+ }
+
public static KeepConstraints defaultConstraints() {
return Defaults.INSTANCE;
}
@@ -103,19 +107,66 @@
return getConstraintsMatching(c -> c.validForMethod() || c.validForField());
}
+ private static class All extends KeepConstraints {
+
+ private static final All INSTANCE = new All();
+
+ private final Set<KeepConstraint> constraints =
+ ImmutableSet.of(
+ KeepConstraint.lookup(),
+ KeepConstraint.name(),
+ KeepConstraint.visibilityRelax(),
+ KeepConstraint.visibilityRestrict(),
+ KeepConstraint.neverInline(),
+ KeepConstraint.classInstantiate(),
+ KeepConstraint.classOpenHierarchy(),
+ KeepConstraint.methodInvoke(),
+ KeepConstraint.methodReplace(),
+ KeepConstraint.fieldGet(),
+ KeepConstraint.fieldSet(),
+ KeepConstraint.fieldReplace(),
+ KeepConstraint.genericSignature(),
+ KeepConstraint.annotationsAll());
+
+ @Override
+ Set<KeepConstraint> getConstraints() {
+ return constraints;
+ }
+
+ @Override
+ public String toString() {
+ return "KeepConstraints.All{}";
+ }
+
+ @Override
+ public Set<KeepAttribute> getRequiredKeepAttributes() {
+ Set<KeepAttribute> attributes = new HashSet<>();
+ getConstraints().forEach(c -> c.addRequiredKeepAttributes(attributes));
+ return attributes;
+ }
+
+ @Override
+ public KeepOptions convertToKeepOptions(KeepOptions defaultOptions) {
+ return KeepOptions.keepAll();
+ }
+ }
+
private static class Defaults extends KeepConstraints {
private static final Defaults INSTANCE = new Defaults();
+ private final Set<KeepConstraint> constraints =
+ ImmutableSet.of(
+ KeepConstraint.lookup(),
+ KeepConstraint.name(),
+ KeepConstraint.classInstantiate(),
+ KeepConstraint.methodInvoke(),
+ KeepConstraint.fieldGet(),
+ KeepConstraint.fieldSet());
+
@Override
Set<KeepConstraint> getConstraints() {
- return ImmutableSet.of(
- KeepConstraint.lookup(),
- KeepConstraint.name(),
- KeepConstraint.classInstantiate(),
- KeepConstraint.methodInvoke(),
- KeepConstraint.fieldGet(),
- KeepConstraint.fieldSet());
+ return constraints;
}
@Override
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepOptions.java b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepOptions.java
index 284a0ac..dde505d 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepOptions.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/ast/KeepOptions.java
@@ -23,7 +23,8 @@
OPTIMIZING,
OBFUSCATING,
ACCESS_MODIFICATION,
- ANNOTATION_REMOVAL
+ ANNOTATION_REMOVAL,
+ SIGNATURE_REMOVAL,
}
public static KeepOptions keepAll() {
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/keeprules/KeepRuleExtractorOptions.java b/src/keepanno/java/com/android/tools/r8/keepanno/keeprules/KeepRuleExtractorOptions.java
index f155852..37169b0 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/keeprules/KeepRuleExtractorOptions.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/keeprules/KeepRuleExtractorOptions.java
@@ -26,6 +26,11 @@
}
@Override
+ public boolean hasAllowSignatureRemovalOptionSupport() {
+ return false;
+ }
+
+ @Override
public boolean hasFieldTypeBackReference() {
return false;
}
@@ -65,6 +70,12 @@
}
@Override
+ public boolean hasAllowSignatureRemovalOptionSupport() {
+ // There is no allow option for signature removal.
+ return false;
+ }
+
+ @Override
public boolean hasFieldTypeBackReference() {
return true;
}
@@ -103,6 +114,8 @@
public abstract boolean hasAllowAnnotationRemovalOptionSupport();
+ public abstract boolean hasAllowSignatureRemovalOptionSupport();
+
public abstract boolean hasFieldTypeBackReference();
public abstract boolean hasMethodReturnTypeBackReference();
@@ -117,6 +130,8 @@
return hasAllowAccessModificationOptionSupport();
case ANNOTATION_REMOVAL:
return hasAllowAnnotationRemovalOptionSupport();
+ case SIGNATURE_REMOVAL:
+ return hasAllowSignatureRemovalOptionSupport();
default:
return true;
}
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/keeprules/RulePrintingUtils.java b/src/keepanno/java/com/android/tools/r8/keepanno/keeprules/RulePrintingUtils.java
index b7c8fbb..b7175dd 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/keeprules/RulePrintingUtils.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/keeprules/RulePrintingUtils.java
@@ -353,6 +353,8 @@
return "accessmodification";
case ANNOTATION_REMOVAL:
return "annotationremoval";
+ case SIGNATURE_REMOVAL:
+ return "signatureremoval";
default:
throw new Unimplemented();
}
diff --git a/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationMatcher.java b/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationMatcher.java
index 4df970e..19a0d8b 100644
--- a/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationMatcher.java
+++ b/src/main/java/com/android/tools/r8/shaking/rules/KeepAnnotationMatcher.java
@@ -23,6 +23,7 @@
import com.android.tools.r8.keepanno.ast.KeepConstraint.FieldGet;
import com.android.tools.r8.keepanno.ast.KeepConstraint.FieldReplace;
import com.android.tools.r8.keepanno.ast.KeepConstraint.FieldSet;
+import com.android.tools.r8.keepanno.ast.KeepConstraint.GenericSignature;
import com.android.tools.r8.keepanno.ast.KeepConstraint.Lookup;
import com.android.tools.r8.keepanno.ast.KeepConstraint.MethodInvoke;
import com.android.tools.r8.keepanno.ast.KeepConstraint.MethodReplace;
@@ -228,6 +229,11 @@
}
@Override
+ public void onGenericSignature(GenericSignature constraint) {
+ joiner.disallowSignatureRemoval();
+ }
+
+ @Override
public void onAnnotation(Annotation constraint) {
KeepAnnotationPattern pattern = constraint.asAnnotationPattern();
if (pattern.getNamePattern().isAny()) {
diff --git a/src/test/java/com/android/tools/r8/keepanno/api/genericsignature/KeepGenericSignaturesApiTest.java b/src/test/java/com/android/tools/r8/keepanno/api/genericsignature/KeepGenericSignaturesApiTest.java
new file mode 100644
index 0000000..c4e44de
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/keepanno/api/genericsignature/KeepGenericSignaturesApiTest.java
@@ -0,0 +1,79 @@
+// Copyright (c) 2024, 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.keepanno.api.genericsignature;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
+
+import com.android.tools.r8.JavaCompilerTool;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.keepanno.KeepAnnoParameters;
+import com.android.tools.r8.keepanno.KeepAnnoTestBase;
+import com.android.tools.r8.keepanno.KeepAnnoTestUtils;
+import com.android.tools.r8.utils.Box;
+import com.android.tools.r8.utils.ListUtils;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.nio.file.Path;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+
+@RunWith(Parameterized.class)
+public class KeepGenericSignaturesApiTest extends KeepAnnoTestBase {
+
+ static final String EXPECTED = StringUtils.lines("Hello, world", "hello, again!");
+
+ @Parameter public KeepAnnoParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static List<KeepAnnoParameters> data() {
+ return createParameters(getTestParameters().withDefaultCfRuntime().build());
+ }
+
+ public List<Class<?>> getLibraryClasses() {
+ return ImmutableList.of(MyValueBox.class, MyOtherValueBox.class);
+ }
+
+ public List<Class<?>> getClientClasses() {
+ return ImmutableList.of(MyValueBoxClient.class);
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForKeepAnno(parameters)
+ .addProgramClasses(getLibraryClasses())
+ .addProgramClasses(getClientClasses())
+ .run(MyValueBoxClient.class)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ @Test
+ public void testSeparateCompilation() throws Exception {
+ assumeFalse(parameters.isReference());
+ assertTrue(parameters.isShrinker());
+ Box<Path> lib = new Box<>();
+ testForKeepAnno(parameters)
+ .addProgramClasses(getLibraryClasses())
+ .applyIfShrinker(b -> lib.set(b.compile().writeToZip()));
+ assertNotNull(lib.get());
+
+ // This checks that we can compile up against the library from Java source.
+ // Doing so requires the generic signature to be kept.
+ Path clientOut =
+ JavaCompilerTool.create(parameters.parameters().asCfRuntime(), temp)
+ .addSourceFiles(
+ ListUtils.map(getClientClasses(), ToolHelper::getSourceFileForTestClass))
+ .addClasspathFiles(lib.get(), KeepAnnoTestUtils.getKeepAnnoLib(temp))
+ .compile();
+
+ testForRuntime(parameters.parameters())
+ .addRunClasspathFiles(lib.get(), clientOut)
+ .run(parameters.getRuntime(), MyValueBoxClient.class)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/keepanno/api/genericsignature/MyOtherValueBox.java b/src/test/java/com/android/tools/r8/keepanno/api/genericsignature/MyOtherValueBox.java
new file mode 100644
index 0000000..392f80d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/keepanno/api/genericsignature/MyOtherValueBox.java
@@ -0,0 +1,29 @@
+// Copyright (c) 2024, 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.keepanno.api.genericsignature;
+
+import com.android.tools.r8.keepanno.annotations.KeepConstraint;
+import com.android.tools.r8.keepanno.annotations.KeepItemKind;
+import com.android.tools.r8.keepanno.annotations.MemberAccessFlags;
+import com.android.tools.r8.keepanno.annotations.UsedByReflection;
+import java.util.function.Function;
+
+// Explicitly keeping the public member signatures (and holder) can be used in place of KeepForApi.
+@UsedByReflection(
+ kind = KeepItemKind.CLASS_AND_MEMBERS,
+ memberAccess = MemberAccessFlags.PUBLIC,
+ constraintAdditions = KeepConstraint.GENERIC_SIGNATURE)
+public class MyOtherValueBox<S> {
+
+ private final S value;
+
+ public MyOtherValueBox(S value) {
+ this.value = value;
+ }
+
+ public <T> T run(Function<S, T> fn) {
+ return fn.apply(value);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/keepanno/api/genericsignature/MyValueBox.java b/src/test/java/com/android/tools/r8/keepanno/api/genericsignature/MyValueBox.java
new file mode 100644
index 0000000..8526488
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/keepanno/api/genericsignature/MyValueBox.java
@@ -0,0 +1,23 @@
+// Copyright (c) 2024, 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.keepanno.api.genericsignature;
+
+import com.android.tools.r8.keepanno.annotations.KeepForApi;
+import java.util.function.Function;
+
+// Default KeepForApi will retain everything, including generic signatures.
+@KeepForApi
+public class MyValueBox<S> {
+
+ private final S value;
+
+ public MyValueBox(S value) {
+ this.value = value;
+ }
+
+ public <T> T run(Function<S, T> fn) {
+ return fn.apply(value);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/keepanno/api/genericsignature/MyValueBoxClient.java b/src/test/java/com/android/tools/r8/keepanno/api/genericsignature/MyValueBoxClient.java
new file mode 100644
index 0000000..796eef3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/keepanno/api/genericsignature/MyValueBoxClient.java
@@ -0,0 +1,24 @@
+// Copyright (c) 2024, 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.keepanno.api.genericsignature;
+
+import com.android.tools.r8.keepanno.annotations.KeepItemKind;
+import com.android.tools.r8.keepanno.annotations.UsedByReflection;
+import java.util.Arrays;
+import java.util.List;
+
+public class MyValueBoxClient {
+
+ @UsedByReflection(kind = KeepItemKind.CLASS_AND_METHODS)
+ public static void main(String[] args) {
+ System.out.println(
+ new MyValueBox<>(Arrays.asList("Hello", "world"))
+ .run((List<String> xs) -> String.join(", ", xs)));
+
+ System.out.println(
+ new MyOtherValueBox<>(Arrays.asList("hello", "again!"))
+ .run((List<String> xs) -> String.join(", ", xs)));
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java b/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java
index bb5de23..2ebb483 100644
--- a/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java
+++ b/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java
@@ -132,6 +132,8 @@
enumRef(KEEP_CONSTRAINT, "NEVER_INLINE");
private static final EnumReference CONSTRAINT_CLASS_OPEN_HIERARCHY =
enumRef(KEEP_CONSTRAINT, "CLASS_OPEN_HIERARCHY");
+ private static final EnumReference CONSTRAINT_GENERIC_SIGNATURE =
+ enumRef(KEEP_CONSTRAINT, "GENERIC_SIGNATURE");
static final List<EnumReference> KEEP_CONSTRAINT_VALUES =
ImmutableList.of(
CONSTRAINT_LOOKUP,
@@ -146,7 +148,8 @@
CONSTRAINT_METHOD_REPLACE,
CONSTRAINT_FIELD_REPLACE,
CONSTRAINT_NEVER_INLINE,
- CONSTRAINT_CLASS_OPEN_HIERARCHY);
+ CONSTRAINT_CLASS_OPEN_HIERARCHY,
+ CONSTRAINT_GENERIC_SIGNATURE);
static final ClassReference MEMBER_ACCESS_FLAGS = annoClass("MemberAccessFlags");
private static final EnumReference MEMBER_ACCESS_PUBLIC = enumRef(MEMBER_ACCESS_FLAGS, "PUBLIC");