RFR: 8343580: Type error with inner classes of generic classes in functions generic by outer

Aggelos Biboudis abimpoudis at openjdk.org
Wed May 21 14:36:54 UTC 2025


On Wed, 21 May 2025 14:28:57 GMT, Chen Liang <liach at openjdk.org> wrote:

>> javac determines erroneously that `getter` has a raw type (`G.Getter`). The type of `getter` is deduced as the raw type `Getters<T>.Getter` by javac. Thus, the `Object` in the following example. The question is whether it should be treated as raw or not in the scenario where the qualifying type *is* a type parameter, as in `G.Getter`. In this case `Getter` is inherited from the supertype `Getters<T>`:
>> 
>> 
>> static abstract class Getters<T> {
>>     abstract class Getter {
>>         abstract T get();
>>     }
>> }
>> 
>> static class Usage<T, G extends Getters<T>> {
>>     public T test(G.Getter getter) {
>>         return getter.get(); // incompatible types: Object cannot be converted to T
>>     }
>> }
>> 
>> 
>> It seems that this is a compiler bug. According to 4.8 Raw Types a “rare” type occurs when the inner is a partially raw type but the definition of Getter doesn’t take any type variables, so this is not a case of a "rare" type. `G.Getter` describes a type with a qualifying type being a type parameter which is not raw and moreover there is an instantiation of its bound. Simply not looking into the bounds of `G` seems like a compiler bug.
>
> src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java line 1155:
> 
>> 1153:             if (allparams_field == null) {
>> 1154:                 Type enclosingType = getEnclosingType();
>> 1155:                 if (!enclosingType.isUnbound() && enclosingType.getUpperBound() instanceof Type t) {
> 
> Shouldn't this be a while loop in case you have G bounded by another type variable?

You mean an intersection type? I think you are right. So do you have something like the following, in mind?


static class Usage<T, G extends Getters<T> && SomethingElse> {
    public T test(G.Getter getter) {
        return getter.get(); // incompatible types: Object cannot be converted to T
    }
}


`G` would be raw if `SomethingElse` is raw if its definition is parametric, e.g. `interface SomethingElse<T>` and not raw if its definition is really `interface SomethingElse`. Did you mean that?

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

PR Review Comment: https://git.openjdk.org/jdk/pull/25346#discussion_r2100460377


More information about the compiler-dev mailing list