JDK-8033677 : Compiler fails to perform type-inference for a lambda passed to a generic method
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8
  • Priority: P3
  • Status: Resolved
  • Resolution: Duplicate
  • OS: windows_7
  • CPU: x86_64
  • Submitted: 2014-02-04
  • Updated: 2014-09-09
  • Resolved: 2014-09-09
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
9Resolved
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.8.0-ea"
Java(TM) SE Runtime Environment (build 1.8.0-ea-b121)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b63, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

A DESCRIPTION OF THE PROBLEM :
When a lambda function is wrapped inside a generic method and such method is being passed as an argument of another method, compiler fails to resolve type of the lambda function. 

Surprisingly, it's able to resolve when generics are declared for a class (e.g. MyClass<A>), but fails when generics are declared for a method (e.g. <A> void foo(...)). 

See the attached code example. 


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class LambdaAndGenerics {
    public static interface Predicate<T> {
        boolean test(T t);
    }
    public static <I, T extends I> I lambdaWrapper(final T lambda) {
        return lambda;
    }
    public static void main(String[] args) {
        new DoesNotFail<String, Integer>().start();
        new Fails().start();
    }

    /**
     * Works fine for N, M declared for a class
     */
    static class DoesNotFail<M, N> {
        void start() {
            System.out.println(one(lambdaWrapper(e -> false)));  // compiler works-out types correctly
        }
        String one(Class<N> arg) {
            return "DoesNotFail class: " + arg;
        }
        String one(Predicate<M> arg) {
            return "DoesNotFail predicate: " + arg.test(null);
        }
    }

    /**
     * Fails when N, M are declared for methods
     */
    static class Fails {
        void start() {
            System.out.println(one(lambdaWrapper(e -> false)));  // COMPILER ERRORS "reference to one is ambiguous" + "cannot infer type variables"
            // one(null);  // COMPILER ERROR "reference to one is ambiguous" which is correct
        }
        <N> String one(Class<N> arg) {
            return "Fails class: " + arg;
        }
        <M> String one(Predicate<M> arg) {
            return "Fails predicate: " + arg.test(null);
        }
    }
}

---------- END SOURCE ----------


Comments
Release team: Approved for deferral.
06-02-2014