FULL PRODUCT VERSION :
java version "1.6.0_12"
Java(TM) SE Runtime Environment (build 1.6.0_12-b04)
Java HotSpot(TM) Client VM (build 11.2-b01, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Windows XP version 5.1 running on x86; Cp1252; en_GB (nb)
A DESCRIPTION OF THE PROBLEM :
The type of a ternary expression is an 'intersection type'. Javac is internally using a 'compound type' and displaying that in error messages. These two forms of type are almost the same but they differ for cases where the intersection type consists of just interfaces, as in the example code. Compound types always include a class whereas intersection types don't have to. There is no mention of compound types in the JLS but details can be found at http://zenger.org/jaco/cjava.html. It may be that compound types are a more appropriate for a description of this area of Java but in that case the JLS ought to mention them.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Enter the code in netbeans IDE. Look at the error message and its description of the type of the ternary expression.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The type of the ternary expression is I & W (the lub(K,J)). It is not Object & I & W which is not the lub(K,J).
Reasons (see source code): We are dealing with this case:
JLS 15.25 ...
"Otherwise, the second and third operands are of types S1 and S2 respectively. Let T1 be the type that results from applying boxing conversion to S1, and let T2 be the type that results from applying boxing conversion to S2. The type of the conditional expression is the result of applying capture conversion (��5.1.10) to lub(T1, T2) (��15.12.2.7)."
Therefore we must apply capture conversion to lub(K,J)
In 15.12.2.7 we find
"... lub(U1 ... Uk), computed as follows:
For a type U, we write ST(U) for the set of supertypes of U, and define the erased supertype set of U,
EST(U) = { V | W in ST(U) and V = |W| }
where|W| is the erasure (��4.6) of W."
We therefore have:
ST(K) = {I,W,Object} ST(J) = {I,W,Object}
EST(K)={I,W,Object} EST(J)={I,W,Object}
(From JLS 4.6 "The erasure of every other type is the type itself.")
"EC, is the intersection of all the sets EST(U) for each U in U1 .. Uk. "
Therefore EC = {{I,W,Object}
"MEC = { V | V in EC, and for all W /= V in EC, it is not the case that W <: V}"
Therefore MEC = {I,W} since I <: Object [see JLS 4.10.2 Object is a direct superinterface falling into the case "The type Object, if C is an interface type with no direct superinterfaces" therefore Object :> I and I <: Object]
"Then, define Candidate(W) = CandidateInvocation(W) if W is generic, W otherwise.
Then the inferred type for Tj is
lub(U1 ... Uk) = Candidate(W1) & ... & Candidate(Wr) where Wi, 1 i r, are the elements of MEC."
Therefore lub(K,J) = Candidate(I) & Candidate(W) = I & W. Capture conversion leaves this unchanged.
This not the value 'Object & I & W' shown by the compiler in the error message.
ACTUAL -
The type of the ternary expression is described in the error message as 'java.lang.Object & javaapplication1.I & javaapplication1.W'.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
incompatible types
found: java.lang.Object & javaapplication1.I & javaapplication1.W
required: javaapplication1.ForceError
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package javaapplication1;
interface I {
}
interface W {
}
interface J extends I, W {
}
interface K extends I, W {
}
class ForceError {
};
public class Main {
J j;
K k;
void m() {
ForceError TriggerErrorMessage;
TriggerErrorMessage = (true ? k : j); //Javac claims the type is Object & I & W
}
}
---------- END SOURCE ----------