| Summary: | [1.5][compiler] ecj rejects valid code when a raw cast is done from a class to an interface | ||
|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Ayushman Jain <amj87.iitr> |
| Component: | Core | Assignee: | Srikanth Sankaran <srikanth_sankaran> |
| Status: | VERIFIED DUPLICATE | QA Contact: | |
| Severity: | normal | ||
| Priority: | P3 | CC: | jarthana, Olivier_Thomann |
| Version: | 3.7 | ||
| Target Milestone: | 3.7 M7 | ||
| Hardware: | All | ||
| OS: | All | ||
| Whiteboard: | |||
Note that as given in the above bug, the following should still fail
interface Super<P> {}
class Y implements Super<Integer>{}
interface X extends Super<Double>{}
class S extends Y {}
interface T extends X{}
public class Test{
public static void main(String argv[]) {
S s = null;
T t = null;
t = (T) s;
}
}
I think this is fixed in the BETA_JAVA7 branch. We should double check that and simply backport the fix. I would target 3.7.1 to match the Java 7 behavior when the Java 7 support is released. (In reply to comment #2) > I think this is fixed in the BETA_JAVA7 branch. We should double check that and > simply backport the fix. Fix is already in HEAD, See bug 334493 *** This bug has been marked as a duplicate of bug 334493 *** Verified. |
Eclipse (build I20110514-0800) rejects the following valid code while javac7b138 compiles it fine. interface Super<P> {} class Y implements Super<Integer>{} interface X extends Super<Double>{} class S<L> extends Y {} interface T<L> extends X{} public class Test{ public static void main(String argv[]) { S s = null; // also if I use S<Byte> T t = null; // also if I use T<Byte> t = (T) s; } } This was also a bug in javac 5,6 which was fixed by http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6559182. Quoting the explanation from that bug - "In that example, T<L> has the following supertypes: *) T<L> *) X *) Super<Double> while S<L> has the following supertypes *) S<L> *) Y *) Super<Integer> In our example we have a cast from a type S (raw) to a type T (raw). Since the target type is an interface, the rule to be used for cast is the folowing (from JLS 5.5): "If [source] is a class type: [...] * If [target] is an interface type: o If [source] is not a final class (ยง8.1.1), then, if there exists a supertype X of [target], and a supertype Y of [source], such that both X and Y are provably distinct parameterized types, and that the erasures of X and Y are the same, a compile-time error occurs. Otherwise, the cast is always legal at compile time (because even if [source] does not implement [target], a subclass of S might)." At first it may seems that a compiler error should be raised since there are indeed two provably distinct supertypes of T<L> and S<L>, namely Super<Double> and Super<Integer>. But in the example the target type is a raw type so JLS 4.8 applies "The superclasses (respectively, superinterfaces) of a raw type are the erasures of the superclasses (superinterfaces) of any of its parameterized invocations." The supertypes of the target type T can be rewritten as follows: *) T *) X *) Super it can be seen how, after we pick the correct supertypes for the raw T, the conflict between Super<Integer> and Super<Double> simply disappear. So this code should indeed compile."