JDK-8203322 : unsoundness with wildcards
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 11
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2018-05-16
  • Updated: 2018-06-28
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
I think this is probably a duplicate of JDK-8054941, but it might be useful as another test case. This one doesn't involve lower bounds, or `null`.

The following program contains no casts and compiles cleanly with -Xlint:unchecked,rawtypes, but fails at runtime with a CCE:

```
abstract class T { 

  public static void main(String[] args) {
    Box<String> a = new Box<>("hello");
    Box<Object> b = cast(a);
    b.set(42);
    System.err.println(a.get());
  }

  static class Box<T> {
    private T x;
    Box(T x)      { this.x = x; }
    T get()       { return x;   }   
    void set(T x) { this.x = x; }
  }

  static Box<Object> cast(Box<String> target) {
    return identity(flatten(new Box<Box<?>>(target)));
  }

  static <A> A identity(A x) {
    return x;
  }

  static <B> Box<? extends B> flatten(Box<Box<? extends B>> r) {
    return r.get();
  }
}
```

```
$ javac -fullversion
javac full version "11-ea+13"
$ javac -Xlint:all T.java
$ java T
...
Exception in thread "main" java.lang.ClassCastException: java.base/java.lang.Integer cannot be cast to java.base/java.lang.String
	at T.main(JavacBug.java:7)
```
Comments
Does not appear related to JDK-8054941: there are no malformed types here. This may be related to JDK-8054721: capture bounds in inference are not being handled appropriately. Here's the expected behavior: The instance creation has type 'Box<Box<?>>' The constraint 'Box<Box<?>> <: Box<Box<? extends b>>' reduces to Box<?> <= Box<? extends b> Box<?> = Box<? extends b> ? = ? extends b Object = b Where the nested invocation has return type 'Box<? extends b>', then we have Box<z> = capture(Box<? extends b>) Box<z> <: a And, finally, from the return type of 'identity': a <: Box<Object> So: { a <: Box<Object>, Box<z> <: a, Box<z> = capture(Box<? extends b>), b = Object } Incorporation should yield z = Object, then 'false', because (per the rules in 18.3.2) a capture ivar can't have an equality constraint.
28-06-2018