Type parameters inside super() calls?

Archie Cobbs archie.cobbs at gmail.com
Thu Feb 2 14:33:09 UTC 2023


On Thu, Feb 2, 2023 at 4:18 AM Maurizio Cimadamore <
maurizio.cimadamore at oracle.com> wrote:

> On 02/02/2023 02:04, Archie Cobbs wrote:
>
> In other words the type itself is not a problem. There's no mention of
> types at all in the above two reasons.
>
> Exactly - I came up with the same conclusion in my long-winded reply to
> myself :-)
>

Hah, glad we think alike. At least that makes two of us.


> So one thought experiment is: What would happen if we eliminated all
> restrictions on generic type parameters in static contexts? What would
> actually go wrong?
>
> In other words, my angle is the opposite: if javac blindly followed the
> "static context" rule, what would happen to existing code? What could go
> wrong? And my answer there was: quite a bit, actually. Which leads me to
> think that the "static" rule, while fine in a pre-generics world (and in a
> world where super calls are the first statement in a constructor) is a good
> and concise way to say what we mean. But, in a post-generics world,
> conflating types with expressions (and initializaton only cares about the
> latter) leads to problems - at least if restrictions are to be interpreted
> literally.
>

I agree that something definitely needs to be improved here...

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.
>
Good point, these are definitely two different cases.

So it sounds like we both agree the use of T in a constructor (case #1),
even prior to super(), should be allowed. Of course the 'this' instance,
which happens to have a type involving T, is unavailable, but that's really
an entirely separate issue.

> Allowing access to T from static method as if it was a "real thing"  seems
> like a recipe for disaster:
>
Well in my twisted way of looking at it, a static method is just an
instance method with one less parameter, and yes, it so happens that the
particular parameter that's missing happens to have a type involving T, but
so what? That doesn't affect how we should treat T itself. As in
constructors (case #1), these are two separate issues.

> 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?).
>
I think the answer would be "T is always not known". So you fall into the
same behavior as you would with a Foo<?>.

Referring to the example (btw, I forgot to include the return type of the
method which obviously is float):

- Any call to toFloat() is correct, because T has Number as upper bound.
Same as if the method were not static and you invoked it on a Foo<?>.
- If a static method returns T, then the compiler treats this as if it
returned ? extends Number.
- The synthetic cast for T would always be to Number

I'm NOT saying that allowing static methods would be an intuitive and
obviously beneficial addition to the language. I'm just saying that it
could be done in a reasonably coherent way. The point of that is just to
provide more evidence that it's NOT automatically true that type parameters
should be forbidden from static contexts.

-Archie

-- 
Archie L. Cobbs
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/compiler-dev/attachments/20230202/3f5e6b6d/attachment.htm>


More information about the compiler-dev mailing list