JDK-8323620 : Strip type annotations in Types' utility methods
  • Type: CSR
  • Component: core-libs
  • Sub-Component: javax.lang.model
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 23
  • Submitted: 2024-01-11
  • Updated: 2024-01-26
  • Resolved: 2024-01-25
Related Reports
CSR :  
Description
Summary
-------

Add a method to strip annotations from type mirrors to `javax.lang.model.util.Types` and clarify how existing methods in `Types` treat annotations.

Problem
-------

The current API does not specify how type annotations are propagated, or not, on `Types`' methods and there is no facility to generate a type without its annotations.

Solution
--------
Add the a new method and clarify existing methods.

Specification
-------------

    diff --git a/src/java.compiler/share/classes/javax/lang/model/util/Types.java b/src/java.compiler/share/classes/javax/lang/model/util/Types.java
    index 8c3cc7ba5d98..93b43c777be5 100644
    --- a/src/java.compiler/share/classes/javax/lang/model/util/Types.java
    +++ b/src/java.compiler/share/classes/javax/lang/model/util/Types.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -35,6 +35,10 @@
     /**
      * Utility methods for operating on types.
      *
    + * Where a method returns a type mirror or a collection of type
    + * mirrors, any type mirrors represent types with no type annotations,
    + * unless otherwise indicated.
    + *
      * <p><b>Compatibility Note:</b> Methods may be added to this interface
      * in future releases of the platform.
      *
    @@ -153,6 +157,8 @@ public interface Types {
          * the direct supertypes of a type mirror representing {@code
          * java.lang.Object}.
          *
    +     * Annotations on the direct super types are preserved.
    +     *
          * @param t  the type being examined
          * @return the direct supertypes, or an empty list if none
          * @throws IllegalArgumentException if given a type for an executable, package, or module
    @@ -235,6 +241,8 @@ public interface Types {
         /**
          * {@return an array type with the specified component type}
          *
    +     * Annotations on the component type are preserved.
    +     *
          * @param componentType  the component type
          * @throws IllegalArgumentException if the component type is not valid for
          *          an array
    @@ -245,6 +253,8 @@ public interface Types {
          * {@return a new wildcard type}  Either of the wildcard's
          * bounds may be specified, or neither, but not both.
          *
    +     * Annotations on the bounds are preserved.
    +     *
          * @param extendsBound  the extends (upper) bound, or {@code null} if none
          * @param superBound    the super (lower) bound, or {@code null} if none
          * @throws IllegalArgumentException if bounds are not valid
    @@ -260,6 +270,8 @@ WildcardType getWildcardType(TypeMirror extendsBound,
          * for example, this method may be used to get the
          * parameterized type {@code Set<String>}.
          *
    +     * Annotations on the type arguments are preserved.
    +     *
          * <p> The number of type arguments must either equal the
          * number of the type element's formal type parameters, or must be
          * zero.  If zero, and if the type element is generic,
    @@ -291,6 +303,8 @@ WildcardType getWildcardType(TypeMirror extendsBound,
          * to get the type {@code Outer<String>}, and then invoking
          * this method.
          *
    +     * Annotations on the type arguments are preserved.
    +     *
          * <p> If the containing type is a parameterized type,
          * the number of type arguments must equal the
          * number of {@code typeElem}'s formal type parameters.
    @@ -324,4 +338,29 @@ DeclaredType getDeclaredType(DeclaredType containing,
          *          for the given type
          */
         TypeMirror asMemberOf(DeclaredType containing, Element element);
    +
    +    /**
    +     * {@return a type mirror equivalent to the argument, but with no annotations}
    +     * If the type mirror is a composite type, such as an array type
    +     * or a wildcard type, any constitute types, such as the
    +     * component type of an array and the type of the bounds of a
    +     * wildcard type, also have no annotations, recursively.
    +     *
    +     * <p>For most kinds of type mirrors, the result of
    +     * {@snippet lang="java" :
    +     *   types.isSameType(typeMirror, types.stripAnnotations(typeMirror))
    +     * }
    +     * is {@code true}. The predicate is {@code false} on wildcard
    +     * types for {@linkplain #isSameType(TypeMirror, TypeMirror)
    +     * reasons discussed elsewhere}.
    +     *
    +     * @param t the type mirror
    +     * @param <T> the specific type of type mirror
    +     * @implSpec
    +     * The default implementation throws {@code UnsupportedOperationException}.
    +     * @since 23
    +     */
    +    default <T extends TypeMirror> T stripAnnotations(T t) {
    +        throw new UnsupportedOperationException();
    +    }
     }


Comments
Add spec update for the overload of getDeclaredType as well.
26-01-2024

Added specification update for getDeclaredType to state that annotations on type arguments are preserved.
25-01-2024

Moving to Approved.
25-01-2024

[~jjg] updated the CSR with proposed text from the PR.
24-01-2024

In the new method, the word `equal` in the initial description could be seen as problematic. It's not `.equals` and you don't use `isSameType`. It's also awkward in its phrasing to say `it's equal, but it's different, because there are no annotations`.
23-01-2024