JDK-6227936 : Wrong type of inherited method using specialized type parameter
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 5.0,6
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic,windows_xp
  • CPU: generic,x86
  • Submitted: 2005-02-10
  • Updated: 2010-05-10
  • Resolved: 2006-02-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6
6 b73Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_01-b08)
Java HotSpot(TM) Client VM (build 1.5.0_01-b08, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
When a generic subclass tightens a generic bound of a super class, the compiler doesn't resolve the tightened bound when when referenced across two classes.

A,B,C are all generic classes that  are bound to each other.  A<T extends B> B<T extends C> and C is not generic.   I then make genericized subclasses of these, A1, B1, C1 that  tighten the bounds on the parent classes.

A1 knows that it is bound to B1.  B1 knows that it is bound to C1.  But when you compile A1 and try to reference C1, it loses this generic binding and throws the exception.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the testcase below and see the failure.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Successful compilation
ACTUAL -
Received a cannot find symbol error

ERROR MESSAGES/STACK TRACES THAT OCCUR :
GenericTest.java:20: cannot find symbol
symbol  : method someMethod()
location: class GenericTest.C
            getB().getC().someMethod();
                ^
1 error

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
class GenericTest {
    static class A<T extends B> {
        T myB;
        A(T myB) {this.myB = myB;}
        T getB() {return myB;}
    }
    static class B<T extends C> {
        T myC;
        B(T myB) {this.myC = myC;}
        T getC() {return myC;}
    }
    static class C {
        C() {}
    }

    static class A1<T extends B1> extends A<T> {
        A1(T myB) {super(myB);}
        public void testMethod() {
            // This next line fails, but should work
            getB().getC().someMethod();
            ((C1)getB().getC()).someMethod();
        }
    }
    static class B1<T extends C1> extends B<T> {
        B1(T myC) {super(myC);}
    }
    static class C1 extends C {
        public void someMethod() {}
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
The workaround is that I must make a cast.
###@###.### 2005-2-10 21:42:44 GMT

Comments
SUGGESTED FIX Webrev of changes: http://sa.sfbay/projects/langtools/bugid_summary.pl?bugid=6359951
14-02-2006

EVALUATION The reported program is actually incorrect and shouldn't compile with the current error message. This is because raw types (that is, generic types without type arguments) are used. Fixing that produces this program, which should compile: class GenericTest { static class A<T extends B<?>> { T myB; A(T myB) {this.myB = myB;} T getB() {return myB;} } static class B<T extends C> { T myC; B(T myB) {this.myC = myC;} T getC() {return myC;} } static class C { C() {} } static class A1<T extends B1<?>> extends A<T> { A1(T myB) {super(myB);} public void testMethod() { // This next line fails, but should work getB().getC().someMethod(); ((C1)getB().getC()).someMethod(); } } static class B1<T extends C1> extends B<T> { B1(T myC) {super(myC);} } static class C1 extends C { public void someMethod() {} } } However, javac fails to accept this program and I have fixed that problem instead. The problem was that capture conversion wasn't applied to bounds of type variables. The fix for 6359951 involves changes to the same lines in javac, so these two fixes will have to go together. Also, the fix for 6240565 must be integrated before this fix.
30-12-2005

WORK AROUND class GenericTest { static class A<T extends B<C1>> { T myB; A(T myB) {this.myB = myB;} T getB() {return myB;} } static class B<T extends C> { T myC; B(T myB) {this.myC = myC;} T getC() {return myC;} } static class C { C() {} } static class A1<T extends B1<C1>> extends A<T> { A1(T myB) {super(myB);} public void testMethod() { // This next line fails, but should work getB().getC().someMethod(); ((C1)getB().getC()).someMethod(); } } static class B1<T extends C1> extends B<T> { B1(T myC) {super(myC);} } static class C1 extends C { public void someMethod() {} } }
30-12-2005

EVALUATION This is a bug. I suspect that the problem is wrong substitution of type parameters in superclasses. We should fix this in mustang and consider backporting to tiger depending the complexity of the fix. However, this is not a problem with inference as no generic methods are involved so I have renamed the synopsis. ###@###.### 2005-2-14 18:55:52 GMT
14-02-2005