JDK-6791481 : 15.12.2.6: Excessive erasure of return/thrown types is specified
  • Type: Bug
  • Component: specification
  • Sub-Component: language
  • Affected Version: 5.0,7,8
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2009-01-08
  • Updated: 2015-12-17
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.
Other
tbd_majorUnresolved
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
Reading from JLS 15.12.2.6:

"The result type of the chosen method is determined as follows: [...]
          o Otherwise, if unchecked conversion was necessary for the method to be applicable then the result type is the erasure (��4.6) of the method's declared return type.[...]"

Moreover

"The exception types of the throws clause of the chosen method are determined as follows:[...]
    * If unchecked conversion was necessary for the method to be applicable then the throws clause is composed of the erasure (��4.6) of the types in the method's declared throws clause."

which means that the following programs should *not* compile

Example 1.

class Test<X> {
	X m(Class<X> c) {return null;}
	X x = m((Class)String.class);
}

Example 2.

class Test {
   <T extends Throwable> void foo(Class<T> c, T t) throws T {}
   void test(Exception e) {
      try {
         foo((Class)String.class, e);
      } catch (Exception t) {}
   }   
}

Example 3.

class Test<T extends Throwable>  {
   void foo(Class<T> c, T t) throws T {}
   void test(Exception e) {
      try {
         new Test<Exception>().foo((Class)String.class, e);
      } catch (Exception t) {}
   }   
}

Comments
EVALUATION There are two problems that cause the current wrong behavior: *) Only generic methods are considered when checking as to whether return/thrown types should be erased or not following an unchecked conversion *) Thrown types currently are not erased TODO: investigate the compatibility risk of this change as it could cause compilation errors on programs that used to be accepted.
08-01-2009

SUGGESTED FIX diff -r e2f8f6daee9d src/share/classes/com/sun/tools/javac/comp/Attr.java --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Fri Dec 19 10:39:02 2008 -0800 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Jan 08 13:45:38 2009 +0000 @@ -2377,7 +2377,7 @@ public class Attr extends JCTree.Visitor varParam); } - if (warned && sym.type.tag == FORALL) { + if (warned) { chk.warnUnchecked(env.tree.pos(), "unchecked.meth.invocation.applied", kindName(sym), @@ -2386,10 +2386,10 @@ public class Attr extends JCTree.Visitor rs.methodArguments(argtypes), kindName(sym.location()), sym.location()); - owntype = new MethodType(owntype.getParameterTypes(), - types.erasure(owntype.getReturnType()), - owntype.getThrownTypes(), - syms.methodClass); + owntype = types.erasure(sym.type); } if (useVarargs) { JCTree tree = env.tree; maurizio@maurizio-laptop:/media/data/ws/j
08-01-2009