Incoherent invocation type inference?
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Fri Jan 13 14:12:35 UTC 2017
I think that's correct behavior. When you say something like:
li = get(null);
T will get two constraints:
* an upper bound (from declared bound) : T <: Iterable<String>
* an upper bound (from return type compatibility) : T <: Integer
The language will then infer T = Integer & Iterable<String>, an
intersection type.
Normally this would be fine - but the issue here is that Integer is a
final class, so that intersection type has no witnesses - e.g. there's
no way for get() to construct a type that is both an Integer and an
Iterable<String> - so that will almost always fail - unless get()
returns null.
That said, I'm not aware of any check in the spec for preventing an
intersection type to mention a final class as one of its components so,
while this does look weird, I think the compiler is doing what the
language spec says.
Maurizio
On 13/01/17 13:01, B. Blaser wrote:
> mport java.util.*;
>
> public class Issue {
> <T extends Iterable<String>> T get() { return (T)new ArrayList<String>(); }
> <T extends Iterable<String>> T get(T t) { return (T)new
> ArrayList<String>(); }
>
> void run() {
> List<String> li = null;
> LinkedList<String> ll = null;
> Integer i = null;
>
> li = get(null);
> i = get(null); // Shouldn't compile? and will fail at runtime.
> // i = get(li); // Fails as expected
>
> li = get();
> ll = get(); // OK, but will fail at runtime due to unchecked
> conversion in get().
> i = get(); // Shouldn't compile? and will fail at runtime.
> }
>
> public static void main(String... args) {
> new Issue().run();
> }
> }
More information about the compiler-dev
mailing list