Guava type inference problems

Jonathan Ross jonathan.ross at imc-chicago.com
Tue Nov 19 15:37:01 PST 2013


Hello again,

my problem below is probably also due to a well understood change to the
type inference rules, and I am sorry if this has all been said and done
before, but I really want to understand what's going on here.

Paraphrasing some production 1.7 code using guava, I have essentially the
following:

import java.util.Collection;
import java.util.List;

abstract class TypeTest {

    interface I {}

    public Collection<? extends I> excludeFrom(Collection<? extends I>
include,
            Collection<? extends I> exclude) {
        return copyOf(filter(include, not(in(exclude))));
    }

    interface Predicate<T> {
        boolean apply(T t);
    }

    abstract <T> Predicate<T> in(Collection<? extends T> target);
    abstract <T> Predicate<T> not(Predicate<T> aPredicate);
    abstract <E> List<E> copyOf(Iterable<? extends E> elements);

    abstract <T> Iterable<T> filter(Iterable<T> unfiltered, Predicate<?
super T> predicate);
}


When I compile this with b115, the compiler bails out, with

TypeTest.java:9: error: no suitable method found for copyOf(Iterable<CAP#1>)

        return copyOf(filter(include, not(in(exclude))));

               ^

    method TypeTest.<E#1>copyOf(Iterable<? extends E#1>) is not applicable

      (cannot infer type-variable(s) E#1,T#1,T#2,T#3

        (argument mismatch; Iterable<CAP#2> cannot be converted to
Iterable<? extends CAP#2>))

    method TypeTest.<E#2>copyOf(Collection<? extends E#2>) is not applicable

      (no instance(s) of type variable(s) T#1,T#2,T#3 exist so that
Iterable<T#1> conforms to Collection<? extends E#2>)

  where E#1,T#1,T#2,T#3,E#2 are type-variables:

    E#1 extends Object declared in method <E#1>copyOf(Iterable<? extends
E#1>)

    T#1 extends Object declared in method
<T#1>filter(Iterable<T#1>,Predicate<? super T#1>)

    T#2 extends Object declared in method <T#2>not(Predicate<T#2>)

    T#3 extends Object declared in method <T#3>in(Collection<? extends T#3>)

    E#2 extends Object declared in method <E#2>copyOf(Collection<? extends
E#2>)

  where CAP#1,CAP#2 are fresh type-variables:

    CAP#1 extends I from capture of ? extends I

    CAP#2 extends I from capture of ? extends I

1 error

But if I replace excludeFrom with

    public Collection<? extends I> filter(Collection<? extends I> include,
            Collection<? extends I> exclude) {
        Iterable<? extends I> myFiltered = filter(include,
not(in(exclude)));
        return copyOf(myFiltered);
    }

compilation succeeds. What gives?

Thanks in advance,

Jonathan Ross


More information about the lambda-dev mailing list