-
Type:
Bug
-
Resolution: Fixed
-
Priority:
P4
-
Affects Version/s: 25
-
Component/s: specification
The conditions around the use of a *qualified* `super` method invocation in an
early construction context are incorrect (they are inadvertently the same as for
an unqualified `super` method invocation).
Currently, JLS 15.12.3 reads:
> If the form is TypeName . super . [TypeArguments] Identifier, then:
>
> - It is a compile-time error if the compile-time declaration is abstract.
>
> - It is a compile-time error if the method invocation occurs in a static
> context or in an early construction context of the current class.
>
> - If TypeName denotes a class C, then if the class or interface declaration
> immediately enclosing the method invocation is not C or an inner class of
> C, a compile-time error occurs.
>
> - If TypeName denotes an interface, let E be the class or interface
> declaration immediately enclosing the method invocation. A compile-time
> error occurs if there exists a method, distinct from the compile-time
> declaration, that overrides (9.4.1) the compile-time declaration from a
> direct superclass or direct superinterface of E.
Clearly in the second bullet point, it is not the early construction context of
the current class that we need to worry about.
If we look at JLS 15.12.4.1 we see that the target reference is defined as:
> If the form is TypeName . super . [TypeArguments] Identifier, then if TypeName
> denotes a class, the target reference is the value of TypeName.this;
> otherwise, the target reference is the value of this.
This tells us which early construction context that we need to worry about.
Following this, I think the second bullet point above should be amended thus:
> – It is a compile-time error if the method invocation occurs in a static
> context or in an early construction context of the ~~current~~ class
> **named by TypeName**.
Interestingly, the test in
`test/langtools/tools/javac/8278078/ValidThisAndSuperInConstructorArgTest.java`,
already covers this example, in particular:
```
class InnerClass extends AssertionError {
...
InnerClass() {
super(StaticSubClass.super.get());
}
...
}
```
early construction context are incorrect (they are inadvertently the same as for
an unqualified `super` method invocation).
Currently, JLS 15.12.3 reads:
> If the form is TypeName . super . [TypeArguments] Identifier, then:
>
> - It is a compile-time error if the compile-time declaration is abstract.
>
> - It is a compile-time error if the method invocation occurs in a static
> context or in an early construction context of the current class.
>
> - If TypeName denotes a class C, then if the class or interface declaration
> immediately enclosing the method invocation is not C or an inner class of
> C, a compile-time error occurs.
>
> - If TypeName denotes an interface, let E be the class or interface
> declaration immediately enclosing the method invocation. A compile-time
> error occurs if there exists a method, distinct from the compile-time
> declaration, that overrides (9.4.1) the compile-time declaration from a
> direct superclass or direct superinterface of E.
Clearly in the second bullet point, it is not the early construction context of
the current class that we need to worry about.
If we look at JLS 15.12.4.1 we see that the target reference is defined as:
> If the form is TypeName . super . [TypeArguments] Identifier, then if TypeName
> denotes a class, the target reference is the value of TypeName.this;
> otherwise, the target reference is the value of this.
This tells us which early construction context that we need to worry about.
Following this, I think the second bullet point above should be amended thus:
> – It is a compile-time error if the method invocation occurs in a static
> context or in an early construction context of the ~~current~~ class
> **named by TypeName**.
Interestingly, the test in
`test/langtools/tools/javac/8278078/ValidThisAndSuperInConstructorArgTest.java`,
already covers this example, in particular:
```
class InnerClass extends AssertionError {
...
InnerClass() {
super(StaticSubClass.super.get());
}
...
}
```