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