JDK-8028774 : javac, inference don't seem to deal with target types in a consistent way
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8
  • Priority: P3
  • Status: Resolved
  • Resolution: Duplicate
  • Submitted: 2013-11-21
  • Updated: 2014-05-30
  • Resolved: 2014-05-30
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
8u20Resolved
Related Reports
Duplicate :  
Description
Having this code:

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);
}

javac 8 produces a compiler error. But if excludeFrom is replaced 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);
    }

it works.
Comments
Another test case, provided by Jonathan Ross on lambda-dev: import java.util.Collection; abstract class Test { abstract <T extends Collection<?>> T build(); abstract void use(Collection<?> n); abstract void use(Double s); void f() { use(build()); } }
17-12-2013

Release team: Approved for deferral. Moving to 8-pool until 8u20 target is created
25-11-2013

Inference notes for the simplified example: Typing include: Collection<CAP#1> where CAP#1 <: I Resolving filter(include): Collection<CAP#1> -> Iterable<t> B1: { t = CAP#1 } Resolving copyOf(filter(include)): Iterable<t> -> Iterable<? extends e> where B1 B2: { t = CAP#1, e <: Object, CAP#1 <: e, t <: e } Typing copyOf(filter(include)): List<e> -> Collection<? extends I> B3: { t = CAP#1, e <: I, CAP#1 <: e, t <: e } Resolution: t = CAP#1, e = CAP#1
21-11-2013

Here's how I believe inference should work: Typing exclude: Collection<CAP#1> where CAP#1 <: I Typing include: Collection<CAP#2> where CAP#2 <: I Resolving in(exclude): Collection<CAP#1> -> Collection<? extends t1> B1: { t1 <: Object, CAP#1 <: t1 } Resolving not(in(exclude)): Predicate<t1> -> Predicate<t2> where B1 B2: { t1 <: Object, CAP#1 <: t1, t2 <: Object, CAP#1 <: t2, t1 = t2 } Resolving filter(include, not(in(exclude))): Collection<CAP#2> -> Iterable<t3> { t3 = CAP#2 } Predicate<t2> -> Predicate<? super t3> where B2 B3: { t1 <: Object, CAP#1 <: t1, CAP#2 <: t1, t2 <: Object, CAP#1 <: t2, CAP#2 <: t2, t3 = CAP#2, t1 = t2, t3 <: t1, t3 <: t2 } Resolving copyOf(filter(include, not(in(exclude)))): Iterable<t3> -> Iterable<? extends e> where B3 B4: { t1 <: Object, CAP#1 <: t1, CAP#2 <: t1, t2 <: Object, CAP#1 <: t2, CAP#2 <: t2, t3 = CAP#2, e <: Object, CAP#2 <: e t1 = t2, t3 <: t1, t3 <: t2, t3 <: e } Typing copyOf(filter(include, not(in(exclude)))): List<e> -> Collection<? extends I> B4: { t1 <: Object, CAP#1 <: t1, CAP#2 <: t1, t2 <: Object, CAP#1 <: t2, CAP#2 <: t2, t3 = CAP#2, e <: I, CAP#2 <: e t1 = t2, t3 <: t1, t3 <: t2, t3 <: e } Resolution: t1 = I t2 = I t3 = CAP#2 e = CAP#2
21-11-2013

SQE / OK to fix this in 8
21-11-2013

Release team: Lacks QA approval so putting this on NMI. Sandeep will loop back with QA on this.
21-11-2013

reduced test case: import java.util.Collection; import java.util.List; abstract class TypeTest { interface I {} public Collection<? extends I> filter2(Collection<? extends I> include) { return copyOf(filter(include)); } abstract <E> List<E> copyOf(Iterable<? extends E> elements); abstract <T> Iterable<T> filter(Iterable<T> unfiltered); }
21-11-2013