Type inference: bug or feature?
Justin Dekeyser
justin.dekeyser at gmail.com
Mon Jul 27 10:47:50 UTC 2020
Dear all,
Okay, thank you very much for the many references you gave me!
Indeed I wasn't aware of this specificity of cast expressions you
mentioned, very interesting !
Sorry for the long email chain, though!
Have a nice day,
Justin Dekeyser
On Mon, Jul 27, 2020 at 12:26 PM Maurizio Cimadamore <
maurizio.cimadamore at oracle.com> wrote:
> CC'ing compiler-dev
>
> Hi Justin,
> the behavior you are observing is normal. For a Java expression to be
> able to be influenced by type inference it has to be a poly expression
> (where poly stands for _many_ as in, the same expression can have many
> types).
>
> At the time we did Java 8 we briefly considered making cast expressions
> part of the poly expression dance (like lambdas, method references,
> method calls, parens, new creation expression, conditionals and switch
> expression - see JLS 15.2), but the rule which dictate cast conversion
> (JLS 5.5) are so complex (as they have to take into account possibility
> for unchecked cast, etc.) that it felt like touching them was a very
> risky move, with no clear benefit.
>
> The behavior you see is caused by the fact that the cast expression acts
> as a "shield" - that is, whenever a method call appears after a cast
> expression (as in your case), the method call is type-checked as if it
> were in isolation, and _then_ the result of type checking is validated
> against the cast. In other words, your example is no different than doing:
>
> var x = (List<Integer>)(Object)emptyList(Number.class);
>
>
> That is, the emptyList call will see no meaningful target type (just
> Object), so Number will be inferred and a List<Number> will be returned,
> which will then be incompatible with the type of the cast expression
> (List<Integer>).
>
> Your second set of examples, since it does not make use of cast
> expressions, works as expected, as the target type can freely flow
> inside the method call typing, and thus influence the type inference
> result (e.g. the inference engine now sees two constraints, for Integer
> and for Number, and is of course able to pick the "best" one).
>
> Hope this helps.
>
> Cheers
> Maurizio
>
> On 26/07/2020 18:22, Justin Dekeyser wrote:
> > Dear all,
> >
> > I'm not sure but I think I've found a bug in Java type inference
> mechanism.
> > It may also be a feature, so I'll expose the problem to you below; in
> terms
> > of Integer, Number and List, although you'll quickly realize it will work
> > wrong in any similar situation.
> >
> > Let's assume I have
> >
> > static <U, V extends U> List<U> emptyList(Class<U> magnet) {
> > return Collections.emptyList();
> > }
> >
> > Then the following codes does not compile (for the same reason):
> >
> > var x = (List<Integer>) emptyList(Number.class);
> > List<Integer> x = (List<Integer>) emptyList(Number.class);
> >
> > incompatible types: List<Number> cannot be converted to List<Integer>
> >
> > however, the following do compile:
> >
> > var x = emptyList(Number.class); // inferred to List<Number>
> > List<Integer> x = emptyList(Number.class); // no mistake here, it's
> Integer
> > on the left
> >
> > Is this the expected behavior? Why does casting operation here interfere
> > with type inference like this?
> >
> > Regards,
> >
> > Justin Dekeyser
> >
> >
> >
> >
> > <
> https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail
> >
> > Garanti
> > sans virus. www.avast.com
> > <
> https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail
> >
> > <#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>
>
More information about the core-libs-dev
mailing list