JDK-8028503 : javac, for method references a primitive type can be added as a bound
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2013-11-18
  • Updated: 2017-05-19
  • Resolved: 2014-05-13
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 8 JDK 9
8u20 b15Fixed 9Fixed
Description
For this code:

class Test {
    static <U> Iterable<U> map(Mapper<String, U> mapper) {
        return null;
    }

    static void test() {
        Iterable<Integer> map = map(Test::length);
    }

    public static <T> int length(String s) {
        return 0;
    }
}

interface Mapper<T, U> {
    U map(T t);
}

javac generates this error message:

Test.java:7: error: incompatible types: inference variable U has incompatible bounds
        Iterable<Integer> map = map(Test::length);
                                   ^
    equality constraints: Integer
    lower bounds: Integer,int   <--- primitive type in bound
  where U is a type-variable:
    U extends Object declared in method <U>map(Mapper<String,U>)
1 error

reported by anna.kozlova_at_jetbrains.com in compiler-dev
Comments
If the test case is modified to: class Test { static <U> Iterable<U> map(Mapper<String, U> mapper) { return null; } static void test() { Iterable<Integer> map = map(Test::length); } public static int length(String s) { //<----- remove the unused <T> return 0; } } interface Mapper<T, U> { U map(T t); } there is no primitive bound added.
29-04-2014

This issue can be observed not only for method references. During overload resolution of m(int) in this code: class Test { <Z> Z m(Z z) { return null; } void test() { double d1 = m(1); } } a lower bound = int is added to Z
12-03-2014

Release team: Approved for deferral.
18-02-2014

raising the priority, this is a major mistake.
11-02-2014

Specified behavior: Test::length -> Mapper<String,u> [18.5.1] int -> u [18.2.1.2] Integer -> u [18.2.2] { Integer <: u } Then of of course invocation typing adds u = Integer. No conflict.
11-02-2014