JDK-6400189 : raw types and inference
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2006-03-17
  • Updated: 2017-05-16
  • Resolved: 2012-01-13
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
7 b55Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
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);

SUGGESTED FIX A webrev of this fix is available at the following URL: http://hg.openjdk.java.net/jdk7/tl/langtools/rev/1ee128971f5d

EVALUATION 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.

EVALUATION 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?

EVALUATION 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).

EVALUATION A bug. Fixing this effects compatibility.