|
CSR :
|
|
|
Relates :
|
|
|
Relates :
|
Summary
-------
Remodel the type arguments in Class-File API to make it an algebraic data type, so users can access the bound type more easily and reliably.
Problem
-------
Currently, when the wildcard indicator in TypeArg is not UNBOUNDED, users can safely trust the bound, wrapped in optional, is non-null; but users still have to use a "risky" unwrap code.
Solution
--------
Remodel the TypeArg to have Bounded and Unbounded subinterfaces; the wildcard indicator and bound will only be present in the Bounded subinterface. This model also more closely aligns with the model from JLS: https://docs.oracle.com/javase/specs/jvms/se21/html/jvms-4.html#jvms-4.7.9.1-300-B.4
Specification
-------------
--- a/src/java.base/share/classes/java/lang/classfile/Signature.java
+++ b/src/java.base/share/classes/java/lang/classfile/Signature.java
@@ -185,80 +185,92 @@ public static ClassTypeSig of(ClassTypeSig outerType, String className, TypeArg.
/**
* Models the type argument.
*
+ * @sealedGraph
* @since 22
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
- public sealed interface TypeArg
- permits SignaturesImpl.TypeArgImpl {
+ public sealed interface TypeArg {
/**
- * Indicator for whether a wildcard has default bound, no bound,
- * an upper bound, or a lower bound
- *
- * @since 22
+ * Models an unbounded type argument {@code *}.
+ * @since 23
*/
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
- public enum WildcardIndicator {
-
- /**
- * default bound wildcard (empty)
- */
- DEFAULT,
-
- /**
- * unbounded indicator {@code *}
- */
- UNBOUNDED,
+ public sealed interface Unbounded extends TypeArg permits SignaturesImpl.UnboundedTypeArgImpl {
+ }
- /**
- * upper-bounded indicator {@code +}
- */
- EXTENDS,
+ /**
+ * Models a type argument with an explicit bound type.
+ * @since 23
+ */
+ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
+ public sealed interface Bounded extends TypeArg permits SignaturesImpl.TypeArgImpl {
/**
- * lower-bounded indicator {@code -}
+ * Models a type argument's wildcard indicator.
+ * @since 23
*/
- SUPER;
+ @PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
+ public enum WildcardIndicator {
+
+ /**
+ * No wildcard (empty), an exact type. Also known as
+ * {@index invariant}.
+ */
+ NONE,
+
+ /**
+ * Upper-bound indicator {@code +}. Also known as
+ * {@index covariant}.
+ */
+ EXTENDS,
+
+ /**
+ * Lower-bound indicator {@code -}. Also known as
+ * {@index contravariant}.
+ */
+ SUPER;
+ }
+
+ /** {@return the kind of wildcard} */
+ WildcardIndicator wildcardIndicator();
+
+ /** {@return the signature of the type bound} */
+ RefTypeSig boundType();
}
- /** {@return the wildcard indicator} */
- WildcardIndicator wildcardIndicator();
-
- /** {@return the signature of the type bound, if any} */
- Optional<RefTypeSig> boundType();
-
/**
* {@return a bounded type arg}
* @param boundType the bound
*/
- public static TypeArg of(RefTypeSig boundType) {
+ public static TypeArg.Bounded of(RefTypeSig boundType) {
requireNonNull(boundType);
- return of(WildcardIndicator.DEFAULT, Optional.of(boundType));
+ return bounded(Bounded.WildcardIndicator.NONE, boundType);
}
/**
* {@return an unbounded type arg}
*/
- public static TypeArg unbounded() {
- return of(WildcardIndicator.UNBOUNDED, Optional.empty());
+ public static TypeArg.Unbounded unbounded() {
+ return SignaturesImpl.UnboundedTypeArgImpl.INSTANCE;
}
/**
* {@return an upper-bounded type arg}
* @param boundType the upper bound
*/
- public static TypeArg extendsOf(RefTypeSig boundType) {
+ public static TypeArg.Bounded extendsOf(RefTypeSig boundType) {
requireNonNull(boundType);
- return of(WildcardIndicator.EXTENDS, Optional.of(boundType));
+ return bounded(Bounded.WildcardIndicator.EXTENDS, boundType);
}
/**
* {@return a lower-bounded type arg}
* @param boundType the lower bound
*/
- public static TypeArg superOf(RefTypeSig boundType) {
+ public static TypeArg.Bounded superOf(RefTypeSig boundType) {
requireNonNull(boundType);
- return of(WildcardIndicator.SUPER, Optional.of(boundType));
+ return bounded(Bounded.WildcardIndicator.SUPER, boundType);
}
/**
@@ -266,7 +278,9 @@ public static TypeArg superOf(RefTypeSig boundType) {
* @param wildcard the wild card
* @param boundType optional bound type
*/
- public static TypeArg of(WildcardIndicator wildcard, Optional<RefTypeSig> boundType) {
+ public static TypeArg.Bounded bounded(Bounded.WildcardIndicator wildcard, RefTypeSig boundType) {
+ requireNonNull(wildcard);
+ requireNonNull(boundType);
return new SignaturesImpl.TypeArgImpl(wildcard, boundType);
}
}
|