Clover Knowledge Base : Java 8 code instrumented by Clover fails to compile


Compilation of Java 8 code instrumented by Clover fails when a lambda expression is passed as an argument of a generic method.


Example #1 - overloaded generic methods

For the following code

public class LambdaAndGenerics {
    static interface Predicate<T> {
        boolean test(T t);

    static class Fails {
        void start() {
            System.out.println(goo(e -> false)); // COMPILER ERRORS "reference to goo is ambiguous" + "cannot infer type variables"
        <N> String goo(Class<N> arg) {
            return "Fails class: " + arg;
        <M> String goo(Predicate<M> arg) {
            return "Fails predicate: " + arg.test(null);
    public static void main(String[] args) {
        new Fails().start();

compiler fails with:

java: reference to goo is ambiguous
  both method <N>goo(java.lang.Class<N>) in LambdaAndGenerics.Fails and method <M>goo(LambdaAndGenerics.Predicate<M>) in LambdaAndGenerics.Fails match

java: incompatible types: cannot infer type-variable(s) I,T
    (argument mismatch; java.lang.Class is not a functional interface)

Example #2 - Java 8 streams

The following code:

public static List<String> testMapAndCollectBounds(List<String> input) {
            .map(e -> e.toUpperCase())

fails with a compilation error:

incompatible types: inference variable T has incompatible bounds
equality constraints: java.lang.String
lower bounds: java.lang.Object


The following code:

public static Stream<String> testMapAndFilterBounds(List<String> input) {
            .map(e -> e.toUpperCase())
            .filter(e -> !e.isEmpty());

fails with a compilation error:

incompatible types:<java.lang.Object> cannot be converted to<java.lang.String>



In case of example #1 it's a bug (aka technical limitation) in Oracle's javac compiler which fails to perform type inference for several nested generic types or methods. Roughly speaking, due to performance reasons, a compiler performs simplified method matching:

  • in a first step it tries to match all methods with a given name, no matter of their signature to the lambda expression (i.e. it ignores overloading)
  • in a second step it selects a method which fits the best (i.e. taking the one with the most narrow type)

In means that a compiler fails if you have two (or more) overloaded methods and one (or more) of them does have a functional interface argument, while others don't have.


In case of example #2 this relates with a fact how type of a lambda expression or type of a method reference are being resolved by the compiler. See Java Language Specification, chapters "15.13 Method Reference Expressions" and "15.27 Lambda Expressions" for more details. Due to a fact that an original lambda is being wrapped into Clover's helper method having a signature like this:

<I, T extends I> I lambdaInc(int index, T lambda, int stmtIndex)

this may cause problems when used with generic method having wildcards, such as:

    .map(...)       // <R> Stream<R> map(Function<? super T, ? extends R> mapper)
    .collect(...)   // <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner)



1) Change a lambda function from an expression to a code block, e.g.:

// expression lambda
System.out.println(goo(e -> false));
// block lambda
System.out.println(goo(e -> { return false; }));

Clover uses different instrumentation for these two lambda forms, so a type inference error will not occur for a lambda block.


2) Or disable instrumentation of lambda functions declared as expressions (since Clover 3.2.2).

Use instrumentLambda = "all_but_reference", "block" or "none"

Ant - build.xml
 <clover-setup instrumentLambda="block"/>
Maven - pom.xml
Grails - BuildConfig.groovy
clover {
   instrumentLambda = "block"



Open "Project Properties "> "Clover" page > "Instrumentation" tab. In the "Miscellaneous" box select proper value in "Instrument lambda functions" drop-down.


IntelliJ IDEA:

Open "File" > "Settings" > "Project Settings" > "Clover" page > "Compilation" tab. In the "Miscellaneous" box select proper value in "Instrument lambda functions" drop-down. 


3) Or surround a lambda by ///CLOVER:OFF and ///CLOVER:ON comments, e.g.:

... some code ...
System.out.println(goo(e -> false));
... some code ...


4) Or rename a method which does not have an argument of functional interface type (example #1), e.g.:

static class Works {
    void start() {
        System.out.println(goo(e -> false));
    <M> String goo(Predicate<M> arg) {
        return "goo: " + arg.test(null);
    <M> String goo(SomeFunctionalInterface<M> arg) {
        return "goo: " +;
    <N> String notAGoo(Class<N> arg) { // this is not a functional interface
       return "Class: " + arg;

5) Since Clover 4.0.5 heuristics are applied to rewrite lambda expressions in JDK Stream's and Guava classes' methods into a block form. More details here: Lambda rewriting heuristics. Try upgrading to Clover 4.0.5 and/or use instrumentLambda="expression" or instrumentLambda="all_but_references".

Bug tracker

CLOV-1465 - Instrumentation of expression-like lambdas with no compilation errors in all cases Open

CLOV-1596 - Use heuristics to solve JDK8 Stream compilation errors Closed

CLOV-1762 - Instrumentation of method references with no compilation errors Open