Incoherent invocation type inference?

Remi Forax forax at univ-mlv.fr
Fri Jan 13 14:50:11 UTC 2017


----- Mail original -----
> De: "Maurizio Cimadamore" <maurizio.cimadamore at oracle.com>
> À: "B. Blaser" <bsrbnd at gmail.com>, compiler-dev at openjdk.java.net
> Envoyé: Vendredi 13 Janvier 2017 15:12:35
> Objet: Re: Incoherent invocation type inference?

> 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.

The spec can not use the fact that a class is final because it's a source and binary compatible change to remove final for a class.
You will break the encapsulation if the class is used by another class but that's another story.

> 
> Maurizio
> 

Rémi

> 
> 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