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

Maurizio Cimadamore mcimadamore at openjdk.org
Mon Jul 7 17:13:44 UTC 2025


On Mon, 7 Jul 2025 15:21:31 GMT, Aggelos Biboudis <abimpoudis at openjdk.org> wrote:

>> There are various occasions that the qualifier of an _inner type_ needs to be normalized. 
>> 
>> Briefly:
>> 
>> - This occurs when there is an explicit type application in the signature of the method or a type application operation or when type checking an expression operation (e.g., `G.Getter` in the first example, `M.B<?>` in the second example). 
>> - The reference to an inner type may not be explicitly qualified (e.g., `B<?>` which is not qualified but its type needs be calculated as seen from `A<String>.B<?>`).
>> 
>> Semi-formally: 
>> 
>> - A type reference is simple name `R`:
>> 
>>   - `R` is a non-inner class type, nothing to do
>>   - `R` is an inner class type, we need to find an implicit type qualifier `S<T>.R`, where `S` is the class in which `R` is enclosed
>>   - `R` is an array type `A[]`, repeat the analysis for the simple type name `A`, and then use the implicit type qualifier to rewrite the array
>> 
>> - A type reference is a qualified name `Q.R`
>>   
>>   - find the supertype of `Q`, namely `S<T>`, where `S` is the class in which `R` is enclosed
>> 
>> 
>> 
>> // example 1
>> static class Usage1<T, G extends Getters<T>> {
>>   public T test(G.Getter getter) {
>>       return getter.get();
>>   }
>> }
>> 
>> // example 2
>> class A<T> {
>>   protected class B<V> {}
>> 
>>   public static <T, M extends A<T>> void f(Object g) {
>>     @SuppressWarnings("unchecked")
>>     M.B<?> mapping = (M.B<?>) g;
>>   }
>> }
>> 
>> // example 3
>> class A<T> {
>>     class B<W> {
>>         public T rett() { return null; }
>>     }
>> }
>> 
>> class C extends A<String> {
>>     static class D {
>>         {
>>             B<?> b = null;
>>             String s = b.rett();
>>         }
>>     }
>> }
>
> Aggelos Biboudis has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Improve comments of asEnclosingSuper/asOuterSuper

src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 2240:

> 2238:      * with the given symbol. If none exists, return null.
> 2239:      *
> 2240:      * This is typically used when there is an explicit qualification of a type.

I don't think this is quite correct. The "classic" case for `asOuterType` is something like this (AFAIU):


class Sup<F> {
        public F f;
    }

class Outer {
    static class Sub extends Sup<String> {
        class I {
            void test() {
                String f2 = f;
            }
        }
    }
 }


Here, we see an access to a field `f`. The "site" for this method call is `I` (the class where the access comes from). What is the instantiated type of `m()` ? To answer that question we need to:

1. compute an instantiated receiver type -- e.g. some type that is related to `I` and that matches `Sup` (the class where `f` is declared). In this case such type is `Sup<String>`
2. replace the type parameters in the instantiated receiver type  in the (declared) signature of the field -- `[F=String]F` = `String`. That is the field signature we should use.

Step (1) here is typically done using `asOuterType`. This will keep trying with all the enclosing types of the input type. So, first `I`, then `Sub`. It will not try to use `Outer` -- which is correct as inside `I` we can't really access instance members in `Outer` (since `I` is an inner class of `Sub`, and `Sub` is `static`). So, from a coding perspective, using `getEnclosingType()` here is "more correct", as using `enclClass()` would "overshoot".

(That said, since we lookup from inner to outer, it is very likely that `asOuterSuper` and `asEnclosingSuper` yield the same result, even in this case -- although I'd prefer if our code did the correct thing and refused to look into unrelated classes).

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

PR Review Comment: https://git.openjdk.org/jdk/pull/25451#discussion_r2190659241


More information about the compiler-dev mailing list