Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8055219

Handling of non-standard inputs in javax.lang.model.util.Types

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P4 P4
    • tbd
    • 8
    • core-libs
    • None

      The behavior of the javax.lang.model.util.Types methods is very lightly specified, relying primarily on the corresponding definitions in the JLS. This fails, however, to account for the mismatch between the API's concept of "TypeMirror", and the JLS's more restricted concept of "Type".

      In general, inputs like WildcardTypes and UnionTypes are allowed in places that they should not, exposing arbitrary implementation details. In order to have clearly-defined, standard behavior in these cases, and in order to minimize constraints on the implementation to not perturb these implementation details, it is best to limit the set of acceptable inputs and throw more IllegalArgumentExceptions.

      ErrorType is special, because it is designed for error recovery, so this is one case in which the existing behavior is probably okay (but it should be clearly specified).

      It would also be useful to more precisely define what constitutes a "valid" result of methods like ArrayType.getComponentType() and ExecutableType.getReturnType().

      Specific comments:

      ---

      isSameType

      spec: True if the types "represent the same type"; exception for wildcards, which are never "the same" as anything, even themselves (the argument for this behavior doesn't really make sense)

      actual: In general, true if the two types are the same; also true if ExecutableTypes can be made the same with alpha-renaming (as in JLS 8.4.4, 8.4.2); always true when one argument is an ErrorType; and false for all wildcards.

      expected: Unclear whether this is meant to be a true "type" operation, or a more general TypeMirror operation. If restricted to types, should have IAE for WildcardType, NoType, and UnionType. If a more general TypeMirror test, should treat WildcardTypes like other TypeMirrors (do they represent the same thing?). Either way, the behavior of ExecutableType and ErrorType should be clearly stated.

      ---

      isSubtype, isAssignable

      spec: Refers to the JLS definitions; IAE for ExecutableType or packages; behavior of other TypeMirrors unspecified

      actual: Matches the spec, but is a mess outside of that scope. Wildcards: true if same (but false for two instances of the same wildcard); for '? super T' on rhs, recurs on T (as if the wildcard were a type variable). NoTypes: none <: none, void <: void, otherwise false (but I noticed a NPE for Object <: none). Unions: unclear -- for union on lhs true if true for all elements; for union on rhs, maybe discards all but first element? ErrorType: always true

      expected: IAE for WildcardType, NoneType, and UnionType (the concept of subtyping is simply foreign to these constructs, just like for ExecutableType). Need to clearly state ErrorType behavior.

      ---

      contains

      spec: Refers to the JLS definitions; IAE for ExecutableType or packages; behavior of other TypeMirrors unspecified

      actual: Matches spec, with additions: none, void, unions, and primitives contain themselves; ErrorType on either side is always true.

      expected: NPE for TypeMirrors that cannot be type arguments: NoType, UnionType, PrimitiveType. Need to clearly state ErrorType behavior.

      ---

      directSupertypes

      spec: does not define the term "direct supertype", although JLS does (4.10) (undefined for non-types, defined for primitives); IAE for ExecutableType or packages

      actual: WildcardType, ErrorType, PrimitiveType, NONE and VOID (NoTypes): empty list; UnionType: lub of the elements, maybe?

      expected: IAE for WildcardType, UnionType, NoType (if you don't participate in subtyping, you don't have supertypes); primitives should be either IAE or return the actual direct super, as defined by JLS (4.10.1); ErrorType is fine to return an empty list, but this should clarified in the spec

      ---

      erasure

      spec: refers to JLS, which defines erasure for all types and for method signatures (but nothing else); IAE for package name

      actual: WildcardType erases to its erased upper bound; ExecutableType erases each type, along the lines of JLS but generalizing beyond the signature to return and thrown types; UnionType erases the first element; ErrorType and NONE/VOID return the input unchanged

      expected: IAE for WildcardType, UnionType, and NoType; should clarify spec on ErrorType and ExecutableType

      ---

      unboxedType

      spec: IAE when the "given type has no unboxing conversion"

      actual: matches spec

      expected: fine, but could be more explicit that there will always be an IAE for non-DeclaredTypes.

      ---

      capture

      spec: refers to JLS, which defines capture for all types (but nothing else); IAE for executable or package name

      actual: WildcardType, UnionType, NONE/VOID, ErrorType: return the type unchanged; IAE for executable or package

      expected: IAE for non-types (WildcardType, UnionType, NoType); clearly specify that ErrorType returns itself

      ---

      getArrayType

      spec: IAE if an input TypeMirror is "not valid"

      actual: allows creation of primitive arrays, UnionType arrays, and '<none>[]' (!); IAE for WildcardType, ExecutableType, and other NoTypes; no error for ErrorTypes.

      expected: IAE for all inputs that are neither ReferenceType nor PrimitiveType (including IAE for UnionTypes and NONE).

      ---

      getWildcardType

      spec: IAE if an input TypeMirror is "not valid"

      actual: IAE for PrimitiveType, WildcardType, UnionType, ExecutableType, and NoTypes; no error for ErrorTypes.

      expected: behavior is fine, but spec should be more clear -- that is, IAE for all non-ReferenceTypes.

      ---

      getDeclaredType

      spec: IAE if an input TypeMirror is "not valid"

      actual: WildcardTypes, UnionTypes, and ErrorTypes are allowed; IAE for PrimitiveType, ExecutableType, and NoTypes.

      expected: IAE for all inputs that are neither ReferenceType nor WildcardType (including IAE for UnionTypes).

      ---

      asMemberOf

      spec: IAE "if the element is not a valid one for the given type"

      actual: for all type arguments, substitutes them directly into the Element's declared type; e.g., the type of method 'next' in 'Iterator<? super String>' is '()? super String' (!)

      expected: Only ReferenceTypes should be used for substitution; a WildcardType as a type argument should prompt either IAE or capture (I prefer the IAE, because the theoretical justification for performing capture here is a little shaky; compare JLS 3 4.5.2 to JLS 7 4.5.2)

      ---

      Suggested valid component types of TypeMirrors (for inclusion in the javadoc of each TypeMirror):

      ArrayType: componentType is a ReferenceType or PrimitiveType

      DeclaredType: enclosingType is a DeclaredType or NONE; typeArguments are ReferenceTypes or WildcardTypes

      ExecutableType: parameterTypes and thrownTypes are ReferenceTypes or PrimitiveTypes; returnType is ReferenceType, PrimitiveType, or VOID

      IntersectionType: bounds are ReferenceTypes

      TypeVariable: lowerBound and upperBound are ReferenceTypes

      UnionType: alternatives are ReferenceTypes

      WildcardType: extendsBound and superBound are ReferenceTypes

        There are no Sub-Tasks for this issue.

            darcy Joe Darcy
            dlsmith Dan Smith
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: