JDK-8319330 : ExecutableElement.getReceiverType doesn't return receiver types for methods loaded from bytecode
  • Type: CSR
  • Component: tools
  • Sub-Component: javac
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 22
  • Submitted: 2023-11-02
  • Updated: 2023-11-13
  • Resolved: 2023-11-13
Related Reports
CSR :  

Update javac's implementation of `ExecutableElement.getReceiverType()` and `ExecutableType.getReceiverType()` to allow accessing type use annotations on receiver types for methods loaded from bytecode.


The implementation currently returns a `NoType` [type mirror](https://docs.oracle.com/en/java/javase/21/docs/api/java.compiler/javax/lang/model/type/NoType.html) with kind `NONE` whenever the receiver parameter syntax is not present in source.

The receiver parameter syntax is not recoverable from the class file, and it is currently never filled in for methods loaded from bytecode. This means that there is no type to host type annotations, and annotation processors are unable to access type annotations on receiver parameters loaded from bytecode.


If a type annotation is present on the receiver type of a method read from bytecode, the implementation should infer that a receiver parameter was present in source, and fill in the receiver type of that method to host the type annotation.


No specification change; behavioral change only.

Prompted by discussion in an earlier version of this CSR, [JDK-8319843](https://bugs.openjdk.org/browse/JDK-8319843) tracks updating the specification to clarify the existing behavior of getReceiverType().
Moving to Approved, contingent on a release note being written to describe the behavioral change.

Moving to Provisional.

[~cushon], sounds like a good plan; administratively moving this CSR back to Draft pending its future update. Thanks.

Understood, thanks. As a next step for the CSR, does it sounds reasonable to: * Update the proposed fix and this CSR to describe the approach of inferring receiver types during class reading if there are annotations on the receiver type * File a separate issue to consider updating the javadoc on getReceiverType() and the disclaimer in the javax.lang.model.element package docs to provide more detail on the situations where getReceiverType() returns a type

Hi [~cushon], yours is a reasonable reading of the text of `getReceiverType()`, but as you've found, that is not what the method has been doing. Since the method was introduced in the context of type annotations, I think it is a defensible behavior -- and more informative in some sense -- for `getReceiverType()` to only be defined when an explicit receiver type was present. As for class files, if there was an annotation on the receiver type, I think that would be sufficient cause for javac to infer that a receiver type should be created to host that information. HTH

Thanks, I hadn't see that text, and it makes sense that complete fidelity between models based on the source and class files can't be guaranteed. In this case I still think the specification for `getReceiverType()` suggests that the method should return a type for executables that have a receiver, not just for executables that have a receiver that is explicit denoted in source. Is that not the intent behind the language in the javadoc for `getReceiverType()`? The reason I noticed this is that it isn't currently possible to retrieve type annotations on receiver parameters read from class files. If the outcome is that `getReceiverType()` should only return a type for receivers denoted in source, what do you think about having the implementation fill in receiver parameters if the class file contains type annotations that target the receiver type? That seems analogous to the other examples listed in the package docs, e.g. the class reader fills in parameter names and metadata when it can.

Hmm. For various cases, the `javax.lang.model.element` package-level docs contain the following disclaimer: > When used in the context of annotation processing, an accurate model > of the element being represented must be returned. As this is a > language model, the source code provides the fiducial (reference) > representation of the construct in question rather than a > representation in an executable output like a class file. Executable > output may serve as the basis for creating a modeling element. > However, the process of translating source code to executable output > may not permit recovering some aspects of the source code > representation. For example, annotations with source retention cannot > be recovered from class files and class files might not be able to > provide source position information. Names of parameters may not be > recoverable from class files. The modifiers on an element created from > a class file may differ in some cases from an element for the same > declaration created from a source file including: > > - `strictfp` on a class or interface > - `final` on a parameter > - `protected`, `private`, and `static` on classes and interfaces > > Some elements which are mandated may not be marked as such when > created from class files. Additionally, synthetic constructs in a > class file, such as accessor methods used in implementing nested > classes and bridge methods used in implementing covariant returns, are > translation artifacts strictly outside of this model. However, when > operating on class files, it is helpful be able to operate on such > elements, screening them out when appropriate. While receiver types aren't explicitly called out here, they could certainly be added to the list.