Type parameters inside super() calls?

Alex Buckley alex.buckley at oracle.com
Thu Feb 2 00:13:31 UTC 2023


8.1.3 has a nice note about intent:

   "The purpose of a static context is to demarcate code that must not 
refer explicitly or implicitly to the current instance of the class 
whose declaration lexically encloses the static context. Consequently, 
code that occurs in a static context is restricted in the following 
ways: ..."

Beyond that, I'm not sure what to say, because all of this has been in 
place since Java 1.1.

Alex

On 2/1/2023 3:43 PM, Maurizio Cimadamore wrote:
> While I agree that what javac does is against the JLS, is this a javac 
> or a spec bug?
> 
> I mean, consider this hierarchy:
> 
> |class Sup<X> { Sup(X x) { ... } } class Sub<Y> extends Sup<Y> { Sub(Y 
> y) { super(y); } } |
> 
> What the rules are saying is that “y” in the Sub super call should be 
> evaluated in a static context. But that doesn’t make any sense - because 
> Y is not even a valid type in such a static context.
> 
> And yet - this is a valid program. So, if typechecking “y” is correct, 
> then, surely, typechecking “(Y)y” should also be correct? E.g. it seems 
> to me that the use of “static context” here is an “approximation” for 
> the behavior we really want (e.g. no access to instance fields, whether 
> directly or indirectly).
> 
> Maurizio
> 
> On 01/02/2023 22:39, Alex Buckley wrote:
> 
>> 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