JDK-6531090 : Cannot access methods/fields of a captured type belonging to an intersection type
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: generic
  • Submitted: 2007-03-05
  • Updated: 2012-03-22
  • Resolved: 2011-05-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.
7 b26Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
JLS 4.4 Type Variables says:
The members of a type variable X with bound T & I1 ... In are the members of the intersection type (��4.9) T & I1 ... In appearing at the point where the type variable is declared.

JLS 4.9 Intersection Types
The values of an intersection type are those objects that are values of all of the types Ti, for 1in.

The test below declares the generic method "static <W extends F & I2> void method(C<? extends W> arg)" , 
where E - class, F - class that extends E and implements I1; I, I1 - interfaces;
C - generic class that declares type variable <T extends E & I>.
There occures a capture conversion from C<? extends W> to C<S>.

According to 5.1.10 Capture Conversion:
If Ti is a wildcard type argument of the form ? extends Bi, then Si is a fresh type variable whose upper bound is glb(Bi, Ui[A1 := S1, ..., An := Sn]) and whose lower bound is the null type, where glb(V1,... ,Vm) is V1 & ... & Vm. 

So, S has upper bound (E & I) & W.
So, the values of S are those objects that are values of all of the types E, I, W.

But test below fails.
-----------------Test code------------------------
import java.io.PrintStream;

class E {}
class F extends E implements I1 {}
interface I {}
interface I1 {}

class G extends F implements I {}

class C<T extends E & I> {
    T field;

public class type15302 {
    public static void main(String argv[]) {
        System.exit(run(argv, System.out) + 95/*STATUS_TEMP*/);

    public static int run(String argv[], PrintStream out) {
        C<G> arg = new C<G>();
        arg.field = new G();
        return 0/*STATUS_PASSED*/;

    static <W extends F> void method(C<? extends W> arg) {
        F vf = arg.field;
        I vi = arg.field;
        I1 vi1 = arg.field;
        E ve = arg.field;
        W vt = arg.field;
Information:Compilation completed with 4 errors and 0 warnings
Information:4 errors
Information:0 warnings
    Error:Error:line (29)incompatible types
found   : capture#955 of ? extends W
required: javasoft.sqe.tests.lang.type153.type15302.F
    Error:Error:line (31)incompatible types
found   : capture#671 of ? extends W
required: javasoft.sqe.tests.lang.type153.type15302.I1
    Error:Error:line (32)incompatible types
found   : capture#442 of ? extends W
required: javasoft.sqe.tests.lang.type153.type15302.E
    Error:Error:line (33)incompatible types
found   : capture#274 of ? extends W
required: W

SUGGESTED FIX see http://sa.sfbay.sun.com/projects/langtools_data/7/6531090

EVALUATION The descriptions refers to two unrelated bugs: 1) Assigments whose RHS type is an intersection type don't work. This may be regarded as a problem in javac's subtyping algorithm. 2) Method *and possibly field) lookup don't work on receivers whose type is a fresh type variable having as bound an intersection type. Let's look at each error 1) Given a subtype test in the form S <: T, if S is a classtype, javac walks up in S's inheritance tree in order to find a type K that is a supertype of S such that |K| == |T|. Unfortunately a problem occur if S is an intersection type. In this case such a type K is not found and this, in turn, makes the subtyping test to fail. For example the first failing assignment of the above example is: F vf = arg.field where the type of "arg.field" is a captured type whose upper bound is the intersection type F&I. When javac checks the correctness of the above assignment, the subtyping test F&I <: F is issued. Since this subtyping test fails as described above (being F&I an intersection type), javac marks that assignment as wrong. In order to fix this problem the Types.asSuper() method needs to be fixed in order to yield the correct answer in case of intersection types. 2) This problem is due to the method/field resolution process not working properly on members of captured types. In the example reported in the "comments" subsection, all methods are invoked on a receiver that is a captured type (capture conversion comes from the former field access). The filed/method resolution lookup proceeds by recursively visiting all class types in the inheritance tree of a given type in which the field has to be accessed from. In the example we have that e.g. arg.fieldT.a() so basically this triggers a method lookup for a() symbol inside the scope of arg.fieldT's symbol. arg.fieldT is the intersection type F&I, where F is a captured type whose upper bound is the intersection type B&I&I1. The resolution process thus fails when applied to F&I, since the supertype of F&I is F that is a captured type and not a class type as the resolver expects. A way to solve this problem would be to always perform method/field lookup on the upper bound of a given type. This wouldn't change the semantic of standard lookups involving classes, as the upper bound of a classtype is the classtype itself; on the other hand, it would allow for a smooth extension of the resolution process also to those types whose supertype(s) is not a class type.