Incoherent invocation type inference?

Maurizio Cimadamore maurizio.cimadamore at
Mon Jan 16 17:03:28 UTC 2017

On 16/01/17 16:49, B. Blaser wrote:
> 2017-01-16 16:25 GMT+01:00 Maurizio Cimadamore <maurizio.cimadamore at>:
>> On 16/01/17 12:51, Maurizio Cimadamore wrote:
>>> I don't think intersection types are the evil in your example. Even
>>> leaving intersection types aside:
>>> class Issue  {
>>>      <T> T get() { return (T)new ArrayList<String>(); }
>>>      void run() {
>>>          LinkedList<String> ll = null;
>>>          ll = get(); // OK, but will fail at runtime due to unchecked
>>> conversion in get().
>>>      }
>>>      public static void main(String... args) {
>>>          new Issue().run();
>>>      }
>>> }
>>> So, I guess I'm not exactly sure of what we're trying to improve here?
>> To clarify - what I'm saying here is: the main issue is that get() is
>> promising that ArrayList<String> will be compatible with T. This promise is
>> unsound - as T is basically controlled by client code, so it can be fixed to
>> whatever type the client wants. That's the condition that smells, IMHO.
>> It's true that, as Remi pointed out, there are cases where unchecked
>> conversion and return type inference play well together - as in
>> Collections.emptyList - but there's a big difference in that method:
>> public static final <T> List<T> emptyList()
>> The return type here is not a naked type-variable T - but List<T>. So, while
>> the client can control the parameterization (List<String> vs List<Integer>)
>> it *cannot* control the base type (List vs String).
>> The combination of unchecked return assignment and a naked generic method
>> type-variable return are IMHO always a source of smell in generic code -
>> that's what I was referring to with the Lint digression.
>> As far as intersection types are concerned - I sense that it's easier to add
>> new well-formedness rules about such types rather than changing the way in
>> which inference constraints are set up based on finality of a class. Having
>> such checks would also prevent users from spelling bad intersection types in
>> their code (e.g. a cast with an intersection type target - which is possible
>> since Java SE 8).
>> Maurizio
> Intersections seem to be dangerous only in the case of a naked return
> type variable with no parameter provided ("get()" or "get(null)")
> because get() wouldn't know about the return type constraints. We
> could, for example, update the rule as follows: "emit a lint warning
> if the return type T is a naked type variable infered to an
> intersection type and no constraint is given by the actual arguments"?
> Or are you suggesting to modify the rules of intersection types on the
> language side?
I think the Lint warning makes sense for naked return type regardless of 
intersections - as in the example I wrote.

Then, for tightening intersections, we could add more rules on the 
language side. Note that javac already prevents you from creating an 
intersection out of List<Integer> and List<String> (different param of 
the same generic interface), so perhaps something about 'final' should 
be added to (either as an official, specified check, or just as a Lint one).

> Bernard

More information about the compiler-dev mailing list