Type parameters inside super() calls?
Alex Buckley
alex.buckley at oracle.com
Wed Feb 1 22:39:35 UTC 2023
Your reading of the JLS is correct. The cast expression `(T)obj` occurs
in a static context, so the use of T should be disallowed, and javac
should reject the program.
These rules in 8.8.7.1 and 8.1.3 are longstanding, and have not changed
recently, so I'm surprised that javac lets the program through. That
said, JLS16 saw a reworking of 8.1.3 (driven by
https://openjdk.org/jeps/395#Static-members-of-inner-classes) and
perhaps javac got a bit turned around over static contexts.
As an additional test case, make the constructor generic -- `public <U
extends T> TypeParam ...` -- and cast obj to U rather than T -- still
illegal.
Alex
On 2/1/2023 12:45 PM, Archie Cobbs wrote:
> This program compiles without error:
>
> import java.util.concurrent.atomic.*;
> public class TypeParamStaticContext<T> extends AtomicReference<T> {
> public TypeParamStaticContext(Object obj) {
> super((T)obj);
> }
> }
>
> Yet according to my reading of the JLS, the appearance of T inside the
> super() call should be disallowed:
>
> §8.8.7.1 <http://8.8.7.1>:
>
> An explicit constructor invocation statement introduces a static context
> (§8.1.3
> <https://docs.oracle.com/javase/specs/jls/se19/html/jls-8.html#jls-8.1.3>), which limits the use of constructs that refer to the current object. Notably, the keywords |this| and |super| are prohibited in a static context (§15.8.3 <https://docs.oracle.com/javase/specs/jls/se19/html/jls-15.html#jls-15.8.3>, §15.11.2 <https://docs.oracle.com/javase/specs/jls/se19/html/jls-15.html#jls-15.11.2>), as are unqualified references to instance variables, instance methods, and type parameters of lexically enclosing declarations (§6.5.5.1 <https://docs.oracle.com/javase/specs/jls/se19/html/jls-6.html#jls-6.5.5.1>, §6.5.6.1 <https://docs.oracle.com/javase/specs/jls/se19/html/jls-6.html#jls-6.5.6.1>, §15.12.3 <https://docs.oracle.com/javase/specs/jls/se19/html/jls-15.html#jls-15.12.3>).
>
> §6.5.5.1 <http://6.5.5.1>:
>
> If a type name consists of a single /Identifier/, then the identifier
> must occur in the scope of exactly one declaration of a class,
> interface, or type parameter with this name (§6.3
> <https://docs.oracle.com/javase/specs/jls/se19/html/jls-6.html#jls-6.3>), or a compile-time error occurs.
>
> If the declaration denotes a type parameter of a generic class or
> interface C (§8.1.2
> <https://docs.oracle.com/javase/specs/jls/se19/html/jls-8.html#jls-8.1.2>, §9.1.2 <https://docs.oracle.com/javase/specs/jls/se19/html/jls-9.html#jls-9.1.2>), then both of the following must be true, or a compile-time error occurs:
>
> *
>
> The type name does not occur in a static context (§8.1.3
> <https://docs.oracle.com/javase/specs/jls/se19/html/jls-8.html#jls-8.1.3>)
>
> *
>
> If the type name appears in a nested class or interface declaration
> of C, then the immediately enclosing class or interface declaration
> of the type name is an inner class of C.
>
>
> What am I missing?
>
> Thanks,
> -Archie
>
> --
> Archie L. Cobbs
More information about the compiler-dev
mailing list