Incoherent invocation type inference?

B. Blaser bsrbnd at
Mon Jan 16 18:33:09 UTC 2017

2017-01-16 18:03 GMT+01:00 Maurizio Cimadamore <maurizio.cimadamore at>:
> 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.

Ok for this first rule.

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

For the final class, I would be tempted to say that the equality
constraint is "obvious"; but if it isn't compliant with the language
specification, we could explore a Lint warning too...


> Maurizio

More information about the compiler-dev mailing list