JDK-6718388 : 4.9: Specify subtyping of intersection types
  • Type: Bug
  • Component: specification
  • Sub-Component: language
  • Affected Version: 7
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2008-06-24
  • Updated: 2024-04-12
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.
Other
tbdUnresolved
Related Reports
Relates :  
Relates :  
Relates :  
Description
I noticed an apparent hole in the way in which subtyping rules deal with intersection types. Consider the following example

class Test {
   static interface I {}

   static class C2 extends C1 implements I {}

   static class C3 extends C1 implements I {}

   public <T> T m1(T t1, T t2) { return t1; }

   public void test(C2 c2, C3 c3) {
       m1(c2, c3);         }
}

In this case T is inferred to be the intersection type C1&I. If we look at the subtyping rules for intersection types, it's not clear, however, that either C2 or C3 are subtypes of the type C1 & I. This relation should hold, since otherwise it would mean that we are inferring a type that make the selected method unapplicable (since actuals are not subtypes of formals). Any idea on how to fix this?

Currently we only know that the supertypes of an intersection type C&I1&I2 ... &In are C, I1, I2 ... In, respectively.
It seems sensible to say that a classtype CT is a subtype of an intersection type C&I1&I2 ... &In iff CT <:  C &&  CT  <:  I1 ...  &&  CT  <:  In.
however this is not stated in the JLS

Fixing this is crucial in order to properly implement method applicability as described in 15.12.2.2:

"The method m is applicable by subtyping if and only if both of the following conditions hold:

    * For 1in, either:
          o Ai is a subtype (§4.10) of Si (Ai <: Si) or
          o Ai is convertible to some type Ci by unchecked conversion (§5.1.9), and Ci <: Si. 
    * If m is a generic method as described above then Ul <: Bl[R1 = U1, ..., Rp = Up], 1lp. "

As types U1, U2 ... Un are inferred types that might be intersection types. It's quite common to end up with a subtyping test of the kind:

A<T> <: A<? extends B&C> that leads to:
T <: B&C (should be OK if T extends/implements both B and C)
A further problem with intersection types is that they allow a type of the form I<T1> & I<T2> where I is an interface type and T1, T2 are two unrelated types. This can be exploited to produce unpredictable results:

interface B<X> { public X m(); }

class C implements B<String> {}

class A<X extends C> {
   X x;

   A<? extends B<Integer>> b = null; // bound of the captured type var is B<Integer>&C, i.e. B<Integer>&B<String>
   Integer o = b.x.m();  // which m()? - compiles with Eclipse
   String o = b.x.m();  // which m()? - doesn't compile with Eclipse
}

Type variables already require that "The erasures of all constituent types of a bound must be pairwise different, or a compiler-time error occurs." But since intersection types "arise from the process of capture conversion", we should be clear about their form too. JLS 4.9 should say: "The constituent type expressions of an intersection type must be pairwise provably distinct, or a compile-time error occurs."

Comments
EVALUATION Yes. JLS3 only allows an intersection type to be a subtype of some other type, not to have subtypes itself. In general, an intersection type might have all kinds of subtypes, including other intersection types, but for now, specifying simple class subtypes in 4.10 is fine.
28-07-2008