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