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); } }
|