[TYPES] Java generics unsoundness?
Atsushi Igarashi
igarashi at kuis.kyoto-u.ac.jp
Tue Oct 3 11:11:01 EDT 2006
Dear all,
I'm not 100% sure but, as far as I understand, compilers should reject
this program according to JLS.
Here is my understanding:
On p.227, there is a description saying:
It is a compile time error if a type declaration T has a member
method m1 and there exists a method m2 declared in T or a supertype
of T such that all of the following conditions hold:
- m1 and m2 have the same name.
- m2 is accessible from T.
- The signature of m1 is not a subsignature (§8.4.2) of the
signature of m2.
- m1 or some method m1 overrides (directly or indirectly) has the
same erasure as m2 or some method m2 overrides (directly or
indirectly).
In this case, T is B,
m1 is public int compareTo(B b) {...} (declared in B), and
m2 is public int compareTo(Object o) {...} (declared in A).
Then,
1. a type declaration T (=B) has a member method m1.
2. it holds that there exists a method m2 declared in T or a supertype
of T, as A is a supertype of B.
Conditions after "such that" also hold:
- Do m1 and m2 have the same name? Yes.
- Is m2 accessible from T? Yes.
- Is the signature of m1 not a subsignature (§8.4.2) of the signature
of m2? No, because the signatures of m1 and m2 are different and
also the signature of m1 and the _erased_ signature of m2 are
different.
- Does m1 or some method m1 overrides (directly or indirectly) have the same erasure
as m2 or some method m2 overrides (directly or indirectly)?
Yes, m1 overrides Comparable's compareTo(), whose erased signature is
int(Object) and m2's erasure is also int(Object).
Now, all the premises hold, so this should be a compile-time error.
It seems to me that the last condition is checking conflicts among
user-defined methods and bridge methods.
One question remains, though. Is it correct to say that a concrete
method in a class "overrides" (rather than implements) an abstract
method in an interface? My interpretation above use "overrides"
for such a relation.
I've found that the definition of "a method in a class overrides
another in a super _class_" (p.224) and "a method in an _interface_
overrides another in a super _interface_" (p.267) but not "a method in
a class overrides another in an interface that the class implements".
Cheers,
--
Atsushi Igarashi
Graduate School of Informatics
Kyoto University
Yoshida-Honmachi, Sakyo-ku
Kyoto 606-8501,Japan
e-mail: igarashi at kuis.kyoto-u.ac.jp
TEL: +81-75-753-4953
FAX: +81-75-753-4954
At Sun, 1 Oct 2006 23:08:09 +0200,
Erik Ernst wrote:
>
> [ The Types Forum, http://lists.seas.upenn.edu/mailman/listinfo/types-list ]
>
> Dear Eijiro Sumii and all others,
>
> not pretending to be the world authority on this issue, the following
> does seem to apply:
>
> - JLS mentions type erasure (4.6) so this would be part of the
> language, but it is not an inherent property of type erasure that
> these method name clashes arise.
>
> - JLS does not mention bridge methods as far as I know, so
> presumably it should be possible to implement them in a different way
> without violating the language def. To avoid the method clash we
> could use name mangling, i.e., including the types of the type-erased
> arguments in the name of the method (as well as $ or similar, to
> avoid clashes with user-defined names). Call sites would be compiled
> in a context where the argument types are known, so they could easily
> use the correct (mangled) name.
>
> All in all, this seems to be a bug in the implementation.
>
> Of course it is not that easy in practice, e.g., because
> existing .class files would then break en masse...
>
> On Sunday 01 October 2006 03:18, Eijiro Sumii wrote:
> > [..]
> >
> > Dear all,
> >
> > Hiromasa Kido, an undergraduate student in the University of Tokyo,
> > has found the problem below in the implementation of generics in
> > Java. [..]
> >----------------------------------------------------------------------
> > [..]
> > C:\WINDOWS\Temp>type B.java
> > class A{
> > public int compareTo(Object o){
> > return 0;
> > }
> > }
> >
> > class B extends A implements Comparable<B>{
> > public int compareTo(B b){
> > return 0;
> > }
> >
> > public static void main(String[] argv){
> > System.out.println(new B().compareTo(new Object()));
> > }
> > }
> > [..]
> >----------------------------------------------------------------------
> >
> > Here is my understanding (confirmed by Atsushi Igarashi) of the
> > problem: after erasure (i.e., replacing every type variable with the
> > Object class), an auxiliary method (called bridged method) like
> >
> > public int compareTo(Object x){
> > return compareTo((B)x);
> > }
> >
> > is created by the compiler in class B. However, this additional
> > method happens to override A.compareTo and raises an unexpected
> > ClassCastException.
> >
> > We have already submitted a bug report to Sun. My question is: Is
> > this a bug in the compiler, or in the design of the language? On
> > one
> > hand, it is a compiler bug because the bridge method, inserted by
> > the
> > compiler, is doing the harm. On the other hand, it would be hard
> > for
> > any compilers to implement generic interfaces without bridge methods
> > (unless we modify the present JVM). In my understading, such
> > overriding as above is not forbidden in the current language
> > specification (page 227 and page 478 perhaps).
> >
> > Does any expert in this list have a word on this matter...?
> >
> > Thanks in advance,
> >
> > Eijiro Sumii
> > http://www.kb.ecei.tohoku.ac.jp/~sumii/
> >
>
> best regards,
>
> --
> Erik Ernst eernst at daimi.au.dk
> Department of Computer Science, University of Aarhus
> IT-parken, Aabogade 34, DK-8200 Aarhus N, Denmark
More information about the Types-list
mailing list