See the evaluation of compiler bug 6536404.
If the specification is changed, please reopen the compiler bug.
I do not know if the implied changes need would be sound.
Comments
EVALUATION
This is a shorter version of the test case from 6536404:
---
import java.util.*;
interface Buffer {}
class Filter<B extends Collection<D>,D> implements Buffer {}
class JavaBug {
<B1 extends Collection<D1>, D1>
Filter<B1,D1> wrap(B1 buffer) { return null; }
<B2 extends Buffer>
Collection<B2> create(B2 buffer) { return null; }
<B3 extends Collection<D3>, D3>
void work(B3 buffer) { Collection<Filter<B3,D3>> x = create(wrap(buffer)); }
}
---
JavaBug.java:13: incompatible types
found : java.util.Collection<Filter<B3,java.lang.Object>>
required: java.util.Collection<Filter<B3,D3>>
void work(B3 buffer) { Collection<Filter<B3,D3>> x = create(wrap(buffer)); }
^
This error is appropriate. In general, D3 is not Object, so to coerce Filter<B3,Object> to Filter<B3,D3> is unsound.
The solution is to make work() into:
Filter<B3,D3> y = wrap(buffer); // Target typing infers D1 as D3
Collection<Filter<B3,D3>> x = create(y);
Rather than changing work(), can we infer the type of wrap(buffer) as Filter<B3,D3>? It is sometimes possible to infer an unused type argument like D1 on the basis of wrap's Collection<D1> bound (see 6371674), but not here. Target typing based on create()'s formal parameter doesn't help. We have reached the limits of what local inference can reasonably do.