Type parameters inside super() calls?

Remi Forax forax at univ-mlv.fr
Thu Feb 2 11:30:09 UTC 2023


> From: "Maurizio Cimadamore" <maurizio.cimadamore at oracle.com>
> To: "Archie Cobbs" <archie.cobbs at gmail.com>, "Alex Buckley"
> <alex.buckley at oracle.com>
> Cc: "compiler-dev" <compiler-dev at openjdk.java.net>
> Sent: Thursday, February 2, 2023 11:25:10 AM
> Subject: Re: Type parameters inside super() calls?

> On 02/02/2023 02:04, Archie Cobbs wrote:

>> Put another way, a static method is just an instance method without a 'this'
>> instance. So neither issue #1 or #2 is possible. So, no problem, right?

>> You might be able to write code that looks silly, but would it actually be
>> nonsensical?

>> public class Foo<T extends Number> {
>> public static toFloat(T value) {
>> return value.floatValue(); // why not?
>> }
>> }

> IMHO, this is taking it a step too far.

> As I said, I believe the issue stems from using the "static context" trick to
> put restriction on _expressions_ - which then ends up also affecting _types_.

> I do not think the bug has to do with "static context" being ill-defined. There
> is a big difference between using a T in a constructor, and using T in a static
> method:

> * when a constructor is called, you are already initializing a _specific_
> instance, so T is _bound_;
> * when a static method is called, there is no instance, so T is _not bound_, and
> has no real meaning.

> Allowing access to T from static method as if it was a "real thing" seems like a
> recipe for disaster: how do we validate that a call to `toFloat` is correct?
> And, if `toFloat` returned a T, how do we validate that the return type is also
> used correctly at the callsite? And which synthetic cast should be generated
> (given that T not known?).
C# does something like this, 
with the call, Foo<String>.toFloat(), T is equals to String 
by extension, the call Foo.toFloat() is a raw call equivalent to Foo<Number>.toFloat(). 

It works because static fields have the same behavior, you have one static field value per specialization. 

This is not how Java works, and this is great for Valhalla because it means that Java does not have to reified parametrized types (no Foo<Integer> at runtime) but only to attach the type arguments to an existing Class at runtime (Foo + erasure[Integer]). This is an important difference because it means that there is no need to define the subtyping relationship between Foo<Integer> and Foo<Double>. 

> Maurizio

Rémi 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/compiler-dev/attachments/20230202/edd99f33/attachment-0001.htm>


More information about the compiler-dev mailing list