Bug 346051 - [1.5][compiler] ecj rejects valid code when a raw cast is done from a class to an interface
Summary: [1.5][compiler] ecj rejects valid code when a raw cast is done from a class t...
Status: VERIFIED DUPLICATE of bug 334493
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.7   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: 3.7 M7   Edit
Assignee: Srikanth Sankaran CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-05-17 04:36 EDT by Ayushman Jain CLA
Modified: 2011-06-17 09:19 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ayushman Jain CLA 2011-05-17 04:36:43 EDT
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."
Comment 1 Ayushman Jain CLA 2011-05-17 04:39:16 EDT
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;
    }
}
Comment 2 Olivier Thomann CLA 2011-05-17 08:36:38 EDT
I think this is fixed in the BETA_JAVA7 branch. We should double check that and simply backport the fix.
Comment 3 Olivier Thomann CLA 2011-05-17 08:43:19 EDT
I would target 3.7.1 to match the Java 7 behavior when the Java 7 support is released.
Comment 4 Srikanth Sankaran CLA 2011-06-03 05:43:05 EDT
(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 ***
Comment 5 Olivier Thomann CLA 2011-06-17 09:19:09 EDT
Verified.