JDK-8142876 : Javac does not correctly implement wildcards removal from functional interfaces
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2015-11-12
  • Updated: 2015-12-25
  • Resolved: 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.
JDK 9
9 b99Fixed
Related Reports
Relates :  
Description
This program fails to compile:

class Test {
    interface I<R extends Runnable, T> {
         void m();
    }

    {
        I<? extends O, String> succeed = this::ff; //ok
        I<? extends Comparable<String>, String> failed = this::ff; //error
    }

    interface O {}
    private void ff(){}
}


Comments
The problem is caused by a bug in the implementation of the check described in JLS 9.9: "The function type of a parameterized functional interface type I<A1...An>, where one or more of A1...An is a wildcard, is the function type of the non-wildcard parameterization of I, I<T1...Tn>. The non-wildcard parameterization is determined as follows. Let P1...Pn be the type parameters of I with corresponding bounds B1...Bn. For all i (1 ��� i ��� n), Ti is derived according to the form of Ai: If Ai is a type, then Ti = Ai. If Ai is a wildcard, and the corresponding type parameter's bound, Bi, mentions one of P1...Pn, then Ti is undefined and there is no function type. Otherwise: If Ai is an unbound wildcard ?, then Ti = Bi. If Ai is a upper-bounded wildcard ? extends Ui, then Ti = glb(Ui, Bi) (��5.1.10). If Ai is a lower-bounded wildcard ? super Li, then Ti = Li." Javac implementation departs a bit from this text (as the implementation was written prior to the spec). It seems like javac gets this part wrong: " If Ai is a wildcard, and the corresponding type parameter's bound, Bi, mentions one of P1...Pn" As javac is not checking as to whether Bi mentions P1 ... Pn - but instead it's checking if it mentions (the capture of) A1...An. To add to the confusion, javac is not using the declared bounds B1...Bn but it's using the bounds of the corresponding captured variable. So, in this case such a bound would be: Object & Comparable<String> & Runnable And javac is seeing that one of the bound is containing String (which is a type-arg in the original functional interface) and so it declares defeat. This is of course buggy.
12-11-2015