JDK-8203337 : 5.1.6.2: Local inner class in generic method should be treated as generic
  • Type: Bug
  • Component: specification
  • Sub-Component: language
  • Affected Version: 8,9,10,10.0.1,11
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2018-05-17
  • Updated: 2018-05-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 :  
Description
A DESCRIPTION OF THE PROBLEM :
Local inner classes in generic methods should be treated as generic types: casts to them should be unchecked and they should not be allowed to extend Throwable. I suspect this is a problem in the JLS.

See included examples demonstrating this as a type system loophole: there are no unchecked warnings, yet this causes heap pollution. The first example shows that such a cast should be treated as unchecked, and the second that it's not safe to allow such a local inner class in a generic method to extend Throwable.

This (and other bugs) comes from this blog post: http://wouter.coekaerts.be/2018/java-type-system-broken

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
compile and run the code

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
unchecked warnings or compilation errors
ACTUAL -
heap pollution, ClassCastException

---------- BEGIN SOURCE ----------
public class LocalInnerClass {
  static Object prev;
  static <T> T go(T t) {
    class A extends ArrayList<T> { }
    if (prev == null) { // first execution
      A a = new A();
      a.add(t);
      prev = a;
      return null;
    } else { // second execution
      return ((A) prev).get(0);
    }
  }

  public static void main(String[] args) {
    go(1);
    String s = go(""); // ClassCastException
  }
}

public class LocalInnerClassWithException {
  static <T> T go(T in, Object other) {
    class A extends RuntimeException {
      T t;
    }
    if (other != null) { // first execution
      try {
        go(other, null);
      } catch (A a) {
        return a.t; // returns other
      }
      throw new AssertionError(); // unreachable
    } else {
      A a = new A();
      a.t = in;
      throw a;
    }
  }

  public static void main(String[] args) {
    String s = go("", 1); // ClassCastException
  }
}
---------- END SOURCE ----------

FREQUENCY : always



Comments
The suggestion to treat local classes in the scope of type parameters as generic is correct, and consistent with JDK-8030746 (which noted similar problems with member classes).
17-05-2018

There are 2 test cases here 1. LocalInnerClass.java -sh-4.2$ /scratch/fairoz/JAVA/jdk11/jdk-11-ea+13/bin/javac LocalInnerClass.java -sh-4.2$ /scratch/fairoz/JAVA/jdk11/jdk-11-ea+13/bin/java LocalInnerClass Exception in thread "main" java.lang.ClassCastException: java.base/java.lang.Integer cannot be cast to java.base/java.lang.String at LocalInnerClass.main(LocalInnerClass.java:19) 2. LocalInnerClassWithException.java -sh-4.2$ /scratch/fairoz/JAVA/jdk11/jdk-11-ea+13/bin/javac LocalInnerClassWithException.java -sh-4.2$ /scratch/fairoz/JAVA/jdk11/jdk-11-ea+13/bin/java LocalInnerClassWithException Exception in thread "main" java.lang.ClassCastException: java.base/java.lang.Integer cannot be cast to java.base/java.lang.String at LocalInnerClassWithException.main(LocalInnerClassWithException.java:24) Issue is reproducible in all the versions of 8,9,10 and 11.
17-05-2018