Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
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
  
  Include a link with my name & email   

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