RFR: 8357653: Inner classes of type parameters emitted as raw types in signatures

Vicente Romero vromero at openjdk.org
Tue May 27 19:46:50 UTC 2025


On Mon, 26 May 2025 15:51:06 GMT, Aggelos Biboudis <abimpoudis at openjdk.org> wrote:

> In the following example, `G.Getter` is erroneously treated as a raw type by javac:
> 
> 
> static abstract class Getters<X> {
>   abstract class Getter {
>       abstract X get();
>   }
> }
> 
> static class Usage1<T, G extends Getters<T>> {
>   public T test(G.Getter getter) {
>       return getter.get();
>   }
> }
> 
> 
> The (now reverted) https://github.com/openjdk/jdk/pull/25346 attempted to fix this by skipping type variables in the calculation of `allparams()`. 
> 
> While that seemed to fix the type checking error, it was a fragile solution in a number of ways. 
> 
> - `allparams()` is passed to a method that calculates substitutions. This signals that the method adheres to invariants during substitutions where lists of type parameters are expected to be of the same length (for the from and to parts). Affecting directly the `allparams_field` seems not the right approach. 
> - Another observation (thx @liach) was that in the generated bytecode, the fully qualified type of the inner class `G` still appeared as if it originated from a raw type. `assembleClassSig` independently examines `outer` to detect whether it is raw or not.
> - Finally, there is already a proper area in javac, earlier in the pipeline, where javac handles/detects "rare types" (`test/langtools/tools/javac/generics/rare`): That method is `checkId` and specifically `checkIdInternal`. While in the general case the type of an identifier is the symbol's type, `checkIdInternal` computes a new type in two occasions. In one of those occasions, `checkIdInternal` is computing the type when the symbol's type is an inner class. Here, we can start normalizing (by skipping the type variables).
> 
> Moreover, it has been observed that `asEnclosingSuper` is a generalization of `asOuterSuper` and additionally the former is used only in `checkIdInternal`. As a result, this PR performs two simplifications:
> 
> As a first simplification this PR replaces `asOuterSuper` with `asEnclosingSuper`.
> As a second simplification this PR relies only on the owner's `enclClass()` based on the following subsequent observations:
> - An `enclosingType()` call returns the `outer_field` directly and `Type.noType` otherwise (in the case of an inner class it refers to the type of its enclosing instance class.)
> - An `enclClass()` call returns the closest enclosing class and the behavior in `asEnclosingSuper` containing a loop with the condition `t.hasTag(CLASS)` combined with `asSuper(t, sym)` is believed to be the same.
> 
> The test now includes bytecode tests additionally t...

looks sensible to me

-------------

Marked as reviewed by vromero (Reviewer).

PR Review: https://git.openjdk.org/jdk/pull/25451#pullrequestreview-2872391074


More information about the compiler-dev mailing list