|
Quick Lists
|
|
Bug ID:
|
6400189
|
|
Votes
|
1
|
|
Synopsis
|
raw types and inference
|
|
Category
|
java:compiler
|
|
Reported Against
|
|
|
Release Fixed
|
7(b55)
|
|
State
|
10-Fix Delivered,
bug
|
|
Priority:
|
4-Low
|
|
Related Bugs
|
6487370
,
6500912
,
6643627
,
6730568
,
6746196
,
6775110
,
6775192
,
6793936
,
6832557
,
6835568
,
6846972
|
|
Submit Date
|
17-MAR-2006
|
|
Description
|
javac incorrectly accepts this program:
import java.lang.reflect.Constructor;
import java.lang.annotation.Documented;
public class Test {
Constructor c = null;
Documented d = c.getAnnotation(Documented.class);
}
Posted Date : 2006-03-17 16:00:55.0
|
|
Work Around
|
N/A
|
|
Evaluation
|
A bug. Fixing this effects compatibility.
Posted Date : 2006-04-21 16:13:05.0
Constructor<T> has a superclass AccessibleObject which defines getAnnotation(Class<T>). Constructor<T> overrides this method; it does not inherit it. By JLS 4.8:
the type of a constructor, instance method, or non-static field M of a raw type C
that is NOT inherited from its superclass or superinterfaces
is the erasure of its type in the generic declaration corresponding to C.
So the type of Constructor#getAnnotation is the erasure of
<T extends Annotation> T getAnnotation(Class<T>)
which might appear to be
Annotation getAnnotation(Class)
but it's not. JLS 4.6 says a method signature has only its formal parameter types erased, not its return type. The erasure is
<T extends Annotation> T getAnnotation(Class)
so T is left to be inferred from the context - as Documented. (Any other subtype of Annotation would do.)
javac is right to accept the program, but an unchecked warning should be given because use of a raw Constructor changes getAnnotation(Class<T>) to getAnnotation(Class).
Posted Date : 2008-03-21 18:36:33.0
I have a prototype of the compiler that works as described above (it tries not to apply erasure to method return type). I'd like however to express some concerns about this idea of not erasing generic method's return type as I think that this 'feature' would increase the overall mess in the type-system area of the compiler.
I recognize that Alex's idea is appealing at first; it's a good way to preserve compatibility. However (and this has been clearly evident in some emails that I exchanged with Alex some months ago), it's clear that this stuff is not as 'easy' as it seemed at first - there are a lot of exceptions, of sub-rules that have to taken into account and I consider this change quite risky. I know that changing such a delicate section of the JLS as the one describing erasure is in order to accomodate the return type erasure thing is risky too, because it's difficult to realize consequences of this ahead of time. Nevertheless I think that if we pursue this approach of 'non-erasing -method-type-variables-where possible' the changes to the JLS will be way bigger and way more unpredictable (e.g. the JLS will have to provide a comprehensive set of example, each one showing the behaviour of method's return type erasure - there are a lot of exceptions - , etc.).
Bottom line: 6400189 is essentially a bug in method resolution vs. overriding vs. overloading, and I'd like to get this bug fixed without also changing the erasure stuff (as they are really two independent issues). As know, however, fixing 6400189 and preserving method return type erasure (as it is now in javac, Eclipse, and all compilers I'm aware of) will result in the code described in that testcase to be rejected by javac. Would that be acceptable? Can we defer the return-type erasure thing to maybe a different RFE?
Posted Date : 2008-07-02 12:58:27.0
We have decided to erase a method's return type and type parameters (see 6730568). Ignore my previous evaluation here; the return type of c.getAnnotation should be Annotation, and the program should not compile.
Posted Date : 2008-07-28 18:06:55.0
|
|
Comments
|
Submitted On 14-DEC-2006
Mark_Ziesemer
Please see https://bugs.eclipse.org/bugs/show_bug.cgi?id=167952. If this is truly a bug, java.beans.MetaData will fail to compile, and possibly com.sun.jmx.mbeanserver.OpenConverter as well.
Submitted On 26-MAR-2008
mulet
Here is a variation on this testcase, which seem to imply that javac is using a different rule.
Basically, I would expect both (1) and (2) to be treated in the same way, but only obtain errors for (2).
=======================
@interface MyAnnotation {
}
class MyConstructor<V> {
<T extends java.lang.annotation.Annotation> T getAnnotation(Class<T> c) {
return null;
}
}
public class X {
void bar1(java.lang.reflect.Constructor constr, Class<MyAnnotation> ann) {
MyAnnotation a = constr.getAnnotation(ann); // 1
}
void bar2(MyConstructor constr, Class<MyAnnotation> ann) {
MyAnnotation a = constr.getAnnotation(ann); // 2
}
}
=======================
X.java:13: warning: [unchecked] unchecked call to <T>getAnnotation(java.lang.Class<T>) as a member of the raw type MyConstructor
MyAnnotation a = constr.getAnnotation(ann); // 2
^
X.java:13: incompatible types
found : java.lang.annotation.Annotation
required: MyAnnotation
MyAnnotation a = constr.getAnnotation(ann); // 2
^
1 error
1 warning
PLEASE NOTE: JDK6 is formerly known as Project Mustang
|
|
|
 |