JDK-8203340 : Type variable bounds referring to outer class not properly captured
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8,9,10,10.0.1,11
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2018-05-17
  • Updated: 2018-05-22
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 :
The capture conversion of a wildcard for a type variable with a bound referring to an outer class is created incorrectly. It creates a capture type that still has an unresolved type variable in it.
This can expose the type variable outside the scope where it is defined; or cause other type confusion, leading to heap pollution.


---------- BEGIN SOURCE ----------
public class OuterInnerConfusion {
  static class Outer<P> {
    class MyList<I extends P> extends ArrayList<I> {
      MyList(I i) {add(i);}
    }
    P getIt(Outer<?>.MyList<?> myList) {
      // myList is a MyList<capture of ?>, where the capture has upper bound P...
      // but that's supposed to be a different P than the return type P here.
      return myList.get(0); // this should not be valid
    }
  }
  public static void main(String args[]) {
    // ClassCastException
    String s = new Outer<String>().getIt(new Outer<Integer>().new MyList<Integer>(1)); 
  }
}
---------- END SOURCE ----------

FREQUENCY : always



Comments
May be related to the question of how wildcard-parameterized outer classes should be handled. For issues like JDK-8030746, the intent is for all type parameters of outer classes to be treated as parameters of the type, and thus captured. (I suspect what's happening is the outer wildcard is treated as if it were a type and substituted in directly as the upper bound of I, which is nonsensical.)
17-05-2018

This issue is reproducible in latest versions of 8,9 10 and 11 -sh-4.2$ /scratch/fairoz/JAVA/jdk11/jdk-11-ea+13/bin/javac OuterInnerConfusion.java -sh-4.2$ /scratch/fairoz/JAVA/jdk11/jdk-11-ea+13/bin/java OuterInnerConfusion Exception in thread "main" java.lang.ClassCastException: java.base/java.lang.Integer cannot be cast to java.base/java.lang.String at OuterInnerConfusion.main(OuterInnerConfusion.java:17)
17-05-2018

Additional information from submitter == It seems copy-pasting this one caused my IntelliJ to remove one type parameter. The main method should be: String s = new Outer<String>().getIt(new Outer<Integer>().new MyList<Integer>(1)); ==
17-05-2018

Not able to reproduce the issue. This is leading to below error == -sh-4.2$ /scratch/fairoz/JAVA/jdk10.0.1/jdk-10.0.1_GA/bin/javac OuterInnerConfusion.java OuterInnerConfusion.java:18: error: improperly formed type, some parameters are missing new Outer<Integer>().new MyList(1)); ^ Note: OuterInnerConfusion.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. 1 error -sh-4.2$ == Requested submitter for additional information
17-05-2018