Capture conversion and containment  
Author Message
Wouter Coekaerts





PostPosted: 2006-5-18 23:15:00 Top

java-programmer, Capture conversion and containment Hi,

I'm writing a tool that analyses java-code, but I have a problem fully
understanding the rules defined in JLS3 for containment and their
combination with capture conversion.

Take the following classes:
class Box<T> {}
class ABox<T extends A> {}
class A {}

Why (because of which rules) is this type-correct code? :
ABox<? extends A> a1;
ABox<?> a2;
a1 = a2;

(And I really mean "a1 = a2" there, not "a2 = a1")
The extra bounds "? extends A" doesn't really make a difference,
ABox<? extends A> and ABox<?> are equivalent, because that parameter already
has a bound A from the definition of ABox. So, informally I understand why
this code is safe. But my problem is understanding the formal rules by
which we can derive that, and where those rules are defined.

My attempt at understanding this:
The constraint for the assignment is:
capture-of(ABox<?>) <: capture-of(ABox<? extends A>)
the capture of ABox<? extends A> is ABox<_T>
where _T is a fresh type variable with upperbounds A.
the capture of ABox<?> is ABox<_T2>
where _T2 is another fresh type variable, also with upperbounds A.
And ABox<_T2> <: ABox<_T> because _T2 <= _T (_T contains _T2). But why?

I see rules for containment defined (4.5.1.1) for wildcards, but not for
type variables created by capture conversion. While I would actually expect
that only rules for type variables would be needed, as types are always
capture converted before you use them. (And this example is chosen so
that "skipping" this capture conversion step doesn't work.)

Now, intuitively, I would say that one type variable contains another if all
its upperbounds are a supertype of one of the upperbounds of the other, and
all its lowerbounds are a subtype of one of the lowerbounds of the other.
But I'd like to see something like this in writing somewhere, and I can't
find an answer to this in the Java Language Specification or anywhere else.
And this intuitive rule doesn't work for Box<ABox<?>>, because the capture
conversion of that is just Box<ABox<?>> again.
So I'm quite confused about how this actually works.

I'd appreciate some help, or pointers to more information about this.

Wouter.