|
CSR :
|
|
|
Relates :
|
|
|
Relates :
|
Summary
-------
A code that names an inner class is erroneously classified as raw and as a result is erroneously rejected.
Problem
-------
In the example that follows, javac determines erroneously that `getter` has a raw type (`G.Getter`). The type of `getter` is deduced as the raw type `Getters<T>.Getter` which is clearly not, since `T`, the type parameter of `Getters<T>` is not omitted. javac thinks that `G` is raw and raises the `Object cannot be converted to T` message in the following example.
In this example `Getter` is simply an inherited member 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
}
}
```
Not looking into the bounds of `G` is a compiler bug.
A symmetrical situation occurs when there is a type application either explicitly or implicitly qualified and the enclosing type is not fully recalculated, for example the compiler crashes in the following two snippets.
```
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; // explicitly qualified type application
}
}
```
```
class A<T> {
class B<W> {
public T rett() { return null; }
}
}
class C extends A<String> {
static class D {
{
B<?> b = null; // implicitly qualified type application
String s = b.rett();
}
}
}
```
The last examples are related to JDK-8357472.
Solution
--------
javac has the necessary functionality to normalize qualified type paths. Taken from the comment in Attr:
```
// class Tree<A> { class Visitor { ... } }
// class PointTree extends Tree<Point> { ... }
// ...PointTree.Visitor...
//
// Then the type of the last expression above is
// Tree<Point>.Visitor.
```
The compiler performs the necessary traversal while calculating the qualifying type path of `PointTree.Visitor` with the type `Tree<Point>.Visitor`. In that case `PointTree` is a concrete class. The solution fixes the cases where the prefix of the path is not only a concrete class but a type parameter with a bound. In our case the correct type is: `Getters<T>.Getter`. The corresponding issue appears in the visitor method for parameterized types, in Attr, as well.
Specification
-------------
We believe there are no changes needed in the specification but you can find linked the JDK-8030746; a currently open spec bug around the same area -- 4.10: Define subtyping for inner classes of parameterized types.
|