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