JDK-7034922 : 4.9: Clarify membership of intersection types for wildcard parameterizations
  • Type: Bug
  • Component: specification
  • Sub-Component: language
  • Affected Version: 5.0,7,8
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2011-04-07
  • Updated: 2018-05-14
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.
Related Reports
Blocks :  
Blocks :  
Blocks :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
From JLS 3 4.9: " the intersection type has the same members as a class type (Chapter 8, Classes) with an empty body, direct superclass Ck and direct superinterfaces T1', ..., Tn'"

This does not consider the possibility that one of Ck or Ti' may be a wildcard-paramterized type.

<T extends Iterable<?>> void m1() {}
<T extends Iterable<?> & Comparable<?>> void m2() {}

In this case, the members of the supertypes (and, therefore, the members of the intersection) are undefined (4.5.2).

It seems like the right thing to do is to make Ti' = capture(Ti), and similar for Ck.  But some caution is warranted, since capture variables do not otherwise appear in class declarations.

It would also be possible to express the implicit class generically:

Given type C<?> & D<? extends Foo, ? super Bar>

We have class:

class Intersect<S extends Bounds1, T extends Bounds2, U extends Bounds3> implements C<S>, D<T, U> {}

And the members of the intersection are the members of class Intersect<?, ? extends Foo, ? super Bar>

That's a lot of work to specify, though . . .  If nothing else, the fact that it could be done demonstrates that the capture alternative, which works out to the same thing, is fundamentally sound.

Need to explore how a solution here would impact determining the function type of a functional interface intersection type (9.9).

The interaction with capture is also relevant for type inference, as in JDK-6391995: <X extends List<? extends String>> void test(X arg) { String s = arg.get(0); // membership String s = getFirst(arg); // inference } <X> X getFirst(List<X> arg) { return arg.get(0); } If we solve this problem, javac can get rid of the hack 'MethodResultInfo.U' in Resolve.

Also need to consider inheritance from array types, which cannot happen in a class declaration.

Simply defining the members as those of the capture is unsound. For example: <X extends List<?>> void m(X arg1, X arg2) { arg1.add(arg2.get(0)); } void test(List<String> l1, List<Integer> l2) { m(l1, l2); } If we claim the members of X are the members of List<CAP>, then the types in 'add' and 'get' are compatible. Fortunately, javac somehow ends up with 'CAP1' in the type of 'get' and 'CAP2' in the type of 'add'.

A related question is the membership of a type variable with a single wildcard-parameterized upper bound. (One explanation is that the upper bound is a singleton intersection, but I'm not sure this view is consistent throughout JLS and javac.)