8325805: Compiler Implementation for Flexible Constructor Bodies (Second Preview)
Reviewed-by: vromero, jlahoda
This commit is contained in:
parent
e708d135e3
commit
87a06b6ce4
@ -208,7 +208,7 @@ public class Preview {
|
||||
public boolean isPreview(Feature feature) {
|
||||
return switch (feature) {
|
||||
case IMPLICIT_CLASSES -> true;
|
||||
case SUPER_INIT -> true;
|
||||
case FLEXIBLE_CONSTRUCTORS -> true;
|
||||
case PRIMITIVE_PATTERNS -> true;
|
||||
case MODULE_IMPORTS -> true;
|
||||
//Note: this is a backdoor which allows to optionally treat all features as 'preview' (for testing).
|
||||
|
@ -254,7 +254,7 @@ public enum Source {
|
||||
WARN_ON_ILLEGAL_UTF8(MIN, JDK21),
|
||||
UNNAMED_VARIABLES(JDK22, Fragments.FeatureUnnamedVariables, DiagKind.PLURAL),
|
||||
PRIMITIVE_PATTERNS(JDK23, Fragments.FeaturePrimitivePatterns, DiagKind.PLURAL),
|
||||
SUPER_INIT(JDK22, Fragments.FeatureSuperInit, DiagKind.NORMAL),
|
||||
FLEXIBLE_CONSTRUCTORS(JDK22, Fragments.FeatureFlexibleConstructors, DiagKind.NORMAL),
|
||||
MODULE_IMPORTS(JDK23, Fragments.FeatureModuleImports, DiagKind.PLURAL),
|
||||
;
|
||||
|
||||
|
@ -293,7 +293,9 @@ public class Attr extends JCTree.Visitor {
|
||||
void checkAssignable(DiagnosticPosition pos, VarSymbol v, JCTree base, Env<AttrContext> env) {
|
||||
if (v.name == names._this) {
|
||||
log.error(pos, Errors.CantAssignValToThis);
|
||||
} else if ((v.flags() & FINAL) != 0 &&
|
||||
return;
|
||||
}
|
||||
if ((v.flags() & FINAL) != 0 &&
|
||||
((v.flags() & HASINIT) != 0
|
||||
||
|
||||
!((base == null ||
|
||||
@ -304,6 +306,23 @@ public class Attr extends JCTree.Visitor {
|
||||
} else {
|
||||
log.error(pos, Errors.CantAssignValToVar(Flags.toSource(v.flags() & (STATIC | FINAL)), v));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check instance field assignments that appear in constructor prologues
|
||||
if (rs.isEarlyReference(env, base, v)) {
|
||||
|
||||
// Field may not be inherited from a superclass
|
||||
if (v.owner != env.enclClass.sym) {
|
||||
log.error(pos, Errors.CantRefBeforeCtorCalled(v));
|
||||
return;
|
||||
}
|
||||
|
||||
// Field may not have an initializer
|
||||
if ((v.flags() & HASINIT) != 0) {
|
||||
log.error(pos, Errors.CantAssignInitializedBeforeCtorCalled(v));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2779,6 +2798,7 @@ public class Attr extends JCTree.Visitor {
|
||||
}
|
||||
}
|
||||
} else if (!clazztype.tsym.isInterface() &&
|
||||
(clazztype.tsym.flags_field & NOOUTERTHIS) == 0 &&
|
||||
clazztype.getEnclosingType().hasTag(CLASS)) {
|
||||
// Check for the existence of an apropos outer instance
|
||||
rs.resolveImplicitThis(tree.pos(), env, clazztype);
|
||||
|
@ -4060,9 +4060,9 @@ public class Check {
|
||||
break;
|
||||
}
|
||||
|
||||
// If super()/this() isn't first, require "statements before super()" feature
|
||||
// If super()/this() isn't first, require flexible constructors feature
|
||||
if (!firstStatement)
|
||||
preview.checkSourceLevel(apply.pos(), Feature.SUPER_INIT);
|
||||
preview.checkSourceLevel(apply.pos(), Feature.FLEXIBLE_CONSTRUCTORS);
|
||||
|
||||
// We found a legitimate super()/this() call; remember it
|
||||
initCall = methodName;
|
||||
|
@ -1508,7 +1508,7 @@ public class Resolve {
|
||||
(sym.flags() & STATIC) == 0) {
|
||||
if (staticOnly)
|
||||
return new StaticError(sym);
|
||||
if (env1.info.ctorPrologue && (sym.flags_field & SYNTHETIC) == 0)
|
||||
if (env1.info.ctorPrologue && !isAllowedEarlyReference(env1, (VarSymbol)sym))
|
||||
return new RefBeforeCtorCalledError(sym);
|
||||
}
|
||||
return sym;
|
||||
@ -3766,6 +3766,7 @@ public class Resolve {
|
||||
Env<AttrContext> env,
|
||||
TypeSymbol c,
|
||||
Name name) {
|
||||
Assert.check(name == names._this || name == names._super);
|
||||
Env<AttrContext> env1 = env;
|
||||
boolean staticOnly = false;
|
||||
while (env1.outer != null) {
|
||||
@ -3775,7 +3776,7 @@ public class Resolve {
|
||||
if (sym != null) {
|
||||
if (staticOnly)
|
||||
sym = new StaticError(sym);
|
||||
else if (env1.info.ctorPrologue)
|
||||
else if (env1.info.ctorPrologue && !isAllowedEarlyReference(env1, (VarSymbol)sym))
|
||||
sym = new RefBeforeCtorCalledError(sym);
|
||||
return accessBase(sym, pos, env.enclClass.sym.type,
|
||||
name, true);
|
||||
@ -3828,6 +3829,70 @@ public class Resolve {
|
||||
return result.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if an early instance field reference may appear in a constructor prologue.
|
||||
*
|
||||
* <p>
|
||||
* This is only allowed when:
|
||||
* - The field is being assigned a value (i.e., written but not read)
|
||||
* - The field is not inherited from a superclass
|
||||
* - The assignment is not within a lambda, because that would require
|
||||
* capturing 'this' which is not allowed prior to super().
|
||||
*
|
||||
* <p>
|
||||
* Note, this method doesn't catch all such scenarios, because this method
|
||||
* is invoked for symbol "x" only for "x = 42" but not for "this.x = 42".
|
||||
* We also don't verify that the field has no initializer, which is required.
|
||||
* To catch those cases, we rely on similar logic in Attr.checkAssignable().
|
||||
*/
|
||||
private boolean isAllowedEarlyReference(Env<AttrContext> env, VarSymbol v) {
|
||||
|
||||
// Check assumptions
|
||||
Assert.check(env.info.ctorPrologue);
|
||||
Assert.check((v.flags_field & STATIC) == 0);
|
||||
|
||||
// The symbol must appear in the LHS of an assignment statement
|
||||
if (!(env.tree instanceof JCAssign assign))
|
||||
return false;
|
||||
|
||||
// The assignment statement must not be within a lambda
|
||||
if (env.info.isLambda)
|
||||
return false;
|
||||
|
||||
// Get the symbol's qualifier, if any
|
||||
JCExpression lhs = TreeInfo.skipParens(assign.lhs);
|
||||
JCExpression base = lhs instanceof JCFieldAccess select ? select.selected : null;
|
||||
|
||||
// If an early reference, the field must not be declared in a superclass
|
||||
if (isEarlyReference(env, base, v) && v.owner != env.enclClass.sym)
|
||||
return false;
|
||||
|
||||
// OK
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the variable appearance constitutes an early reference to the current class.
|
||||
*
|
||||
* <p>
|
||||
* This means the variable is an instance field of the current class and it appears
|
||||
* in an early initialization context of it (i.e., one of its constructor prologues).
|
||||
*
|
||||
* <p>
|
||||
* Such a reference is only allowed for assignments to non-initialized fields that are
|
||||
* not inherited from a superclass, though that is not enforced by this method.
|
||||
*
|
||||
* @param env The current environment
|
||||
* @param base Variable qualifier, if any, otherwise null
|
||||
* @param v The variable
|
||||
*/
|
||||
public boolean isEarlyReference(Env<AttrContext> env, JCTree base, VarSymbol v) {
|
||||
return env.info.ctorPrologue &&
|
||||
(v.flags() & STATIC) == 0 &&
|
||||
v.owner.kind == TYP &&
|
||||
types.isSubtype(env.enclClass.type, v.owner.type) &&
|
||||
(base == null || TreeInfo.isExplicitThisReference(types, (ClassType)env.enclClass.type, base));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve `c.this' for an enclosing class c that contains the
|
||||
|
@ -399,6 +399,10 @@ compiler.err.cant.inherit.from.final=\
|
||||
compiler.err.cant.ref.before.ctor.called=\
|
||||
cannot reference {0} before supertype constructor has been called
|
||||
|
||||
# 0: symbol or name
|
||||
compiler.err.cant.assign.initialized.before.ctor.called=\
|
||||
cannot assign initialized field ''{0}'' before supertype constructor has been called
|
||||
|
||||
compiler.err.cant.select.static.class.from.param.type=\
|
||||
cannot select a static class from a parameterized type
|
||||
|
||||
@ -3215,8 +3219,8 @@ compiler.misc.feature.unconditional.patterns.in.instanceof=\
|
||||
compiler.misc.feature.implicit.classes=\
|
||||
implicitly declared classes
|
||||
|
||||
compiler.misc.feature.super.init=\
|
||||
statements before super()
|
||||
compiler.misc.feature.flexible.constructors=\
|
||||
flexible constructors
|
||||
|
||||
compiler.misc.feature.module.imports=\
|
||||
module imports
|
||||
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 8325805
|
||||
* @summary Permit non-superclass instance field assignments before this/super in constructors
|
||||
* @compile/fail/ref=DA_DUConstructors.out -XDrawDiagnostics DA_DUConstructors.java
|
||||
* @enablePreview
|
||||
*/
|
||||
|
||||
public class DA_DUConstructors {
|
||||
// identity
|
||||
class C1 {
|
||||
final int x;
|
||||
final int y = x + 1;
|
||||
C1() {
|
||||
x = 12;
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
class C2 {
|
||||
final int x;
|
||||
C2() {
|
||||
this(x = 3); // error
|
||||
}
|
||||
C2(int i) {
|
||||
x = 4;
|
||||
}
|
||||
}
|
||||
|
||||
class C3 {
|
||||
C3(int i) {}
|
||||
}
|
||||
class C4 extends C3 {
|
||||
final int x;
|
||||
C4() {
|
||||
super(x = 3); // ok
|
||||
}
|
||||
}
|
||||
|
||||
class C5 {
|
||||
final int x;
|
||||
final int y = x + 1; // x is not DA
|
||||
C5() {
|
||||
x = 12; super();
|
||||
}
|
||||
C5(int i) {
|
||||
/* no prologue */
|
||||
x = i;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
DA_DUConstructors.java:23:17: compiler.err.var.might.already.be.assigned: x
|
||||
DA_DUConstructors.java:42:23: compiler.err.var.might.not.have.been.initialized: x
|
||||
- compiler.note.preview.filename: DA_DUConstructors.java, DEFAULT
|
||||
- compiler.note.preview.recompile
|
||||
2 errors
|
161
test/langtools/tools/javac/SuperInit/EarlyAssignments.java
Normal file
161
test/langtools/tools/javac/SuperInit/EarlyAssignments.java
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 8325805
|
||||
* @summary Permit non-superclass instance field assignments before this/super in constructors
|
||||
* @compile/fail/ref=EarlyAssignments.out -XDrawDiagnostics EarlyAssignments.java
|
||||
* @enablePreview
|
||||
*/
|
||||
public class EarlyAssignments {
|
||||
|
||||
public static class Inner1 {
|
||||
public int x;
|
||||
|
||||
public Inner1() {
|
||||
x = 123; // OK - "x" belongs to this class
|
||||
this.x = 123; // OK - "x" belongs to this class
|
||||
Inner1.this.x = 123; // OK - "x" belongs to this class
|
||||
super();
|
||||
}
|
||||
|
||||
public Inner1(int y) {
|
||||
y = x; // FAIL - early 'this' reference
|
||||
y = this.x; // FAIL - early 'this' reference
|
||||
y = Inner1.this.x; // FAIL - early 'this' reference
|
||||
super();
|
||||
}
|
||||
|
||||
public class Inner1a extends Inner1 {
|
||||
public int z;
|
||||
public Inner1a(byte value) {
|
||||
Inner1.this.x = value; // OK - "x" belongs to outer class
|
||||
z = super.x; // FAIL - "x" belongs to superclass
|
||||
z = x; // FAIL - "x" belongs to superclass
|
||||
this.z = x; // FAIL - "x" belongs to superclass
|
||||
Inner1a.this.z = x; // FAIL - "x" belongs to superclass
|
||||
Object o1 = Inner1.this; // OK - Inner1 is an outer class
|
||||
Object o2 = Inner1a.this; // FAIL - Inner1a is this class
|
||||
super();
|
||||
}
|
||||
public Inner1a(short value) {
|
||||
x = value; // FAIL - "x" belongs to superclass
|
||||
super();
|
||||
}
|
||||
public Inner1a(char value) {
|
||||
this.x = value; // FAIL - "x" belongs to superclass
|
||||
super();
|
||||
}
|
||||
public Inner1a(int value) {
|
||||
super.x = value; // FAIL - "x" belongs to superclass
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
public class Inner1b {
|
||||
public Inner1b(int value) {
|
||||
Inner1.this.x = value; // OK - "x" belongs to outer class
|
||||
super();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Inner2 extends Inner1 {
|
||||
int y;
|
||||
public Inner2(int value) {
|
||||
y = value; // OK - "y" belongs to this class
|
||||
this.y = value; // OK - "y" belongs to this class
|
||||
x = value; // FAIL - "x" belongs to superclass
|
||||
this.x = value; // FAIL - "x" belongs to superclass
|
||||
Object o1 = this; // FAIL - can't acces 'this' yet
|
||||
Object o2 = Inner2.this; // FAIL - can't acces 'this' yet
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Inner3 {
|
||||
|
||||
public int e;
|
||||
|
||||
public class Inner3a {
|
||||
|
||||
public static int x;
|
||||
|
||||
public Inner3a(int val) {
|
||||
x = val; // OK - "x" is a static field
|
||||
val = x; // OK - "x" is a static field
|
||||
e = val; // OK - "e" belongs to outer class
|
||||
val = e; // OK - "e" belongs to outer class
|
||||
Inner3.this.e = val; // OK - "e" belongs to outer class
|
||||
super();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Inner4 {
|
||||
public int x;
|
||||
|
||||
public Inner4() {
|
||||
x = 0; // OK
|
||||
x = x + 1; // FAIL - illegal early access
|
||||
super();
|
||||
}
|
||||
|
||||
public Inner4(int a) {
|
||||
this.x = 0; // OK
|
||||
this.x = this.x + 1; // FAIL - illegal early access
|
||||
super();
|
||||
}
|
||||
|
||||
public Inner4(char a) {
|
||||
Inner4.this.x = 0; // OK
|
||||
Inner4.this.x = Inner4.this.x + 1; // FAIL - illegal early access
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Inner5 extends Inner4 {
|
||||
public int y;
|
||||
|
||||
public Inner5() {
|
||||
y = x + 1; // FAIL - illegal early access
|
||||
super();
|
||||
}
|
||||
|
||||
public Inner5(int a) {
|
||||
this.y = x + 1; // FAIL - illegal early access
|
||||
super();
|
||||
}
|
||||
|
||||
public Inner5(char a) {
|
||||
Inner5.this.y = x + 1; // FAIL - illegal early access
|
||||
super();
|
||||
}
|
||||
|
||||
public Inner5(short a) {
|
||||
y = super.x + 1; // FAIL - illegal early access
|
||||
super();
|
||||
}
|
||||
|
||||
public Inner5(float a) {
|
||||
y = Inner5.this.x + 1; // FAIL - illegal early access
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Inner6 {
|
||||
public int x = 1;
|
||||
|
||||
public Inner6() {
|
||||
x = 2; // FAIL - illegal early access
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Inner7 {
|
||||
public final int x = 1;
|
||||
|
||||
public Inner7() {
|
||||
x = 2; // FAIL - illegal early access
|
||||
super();
|
||||
}
|
||||
}
|
||||
}
|
28
test/langtools/tools/javac/SuperInit/EarlyAssignments.out
Normal file
28
test/langtools/tools/javac/SuperInit/EarlyAssignments.out
Normal file
@ -0,0 +1,28 @@
|
||||
EarlyAssignments.java:21:17: compiler.err.cant.ref.before.ctor.called: x
|
||||
EarlyAssignments.java:22:17: compiler.err.cant.ref.before.ctor.called: this
|
||||
EarlyAssignments.java:23:23: compiler.err.cant.ref.before.ctor.called: this
|
||||
EarlyAssignments.java:31:21: compiler.err.cant.ref.before.ctor.called: super
|
||||
EarlyAssignments.java:32:21: compiler.err.cant.ref.before.ctor.called: x
|
||||
EarlyAssignments.java:33:26: compiler.err.cant.ref.before.ctor.called: x
|
||||
EarlyAssignments.java:34:34: compiler.err.cant.ref.before.ctor.called: x
|
||||
EarlyAssignments.java:36:36: compiler.err.cant.ref.before.ctor.called: this
|
||||
EarlyAssignments.java:40:17: compiler.err.cant.ref.before.ctor.called: x
|
||||
EarlyAssignments.java:44:21: compiler.err.cant.ref.before.ctor.called: x
|
||||
EarlyAssignments.java:48:22: compiler.err.cant.ref.before.ctor.called: x
|
||||
EarlyAssignments.java:66:13: compiler.err.cant.ref.before.ctor.called: x
|
||||
EarlyAssignments.java:67:17: compiler.err.cant.ref.before.ctor.called: x
|
||||
EarlyAssignments.java:68:25: compiler.err.cant.ref.before.ctor.called: this
|
||||
EarlyAssignments.java:69:31: compiler.err.cant.ref.before.ctor.called: this
|
||||
EarlyAssignments.java:98:17: compiler.err.cant.ref.before.ctor.called: x
|
||||
EarlyAssignments.java:104:22: compiler.err.cant.ref.before.ctor.called: this
|
||||
EarlyAssignments.java:110:35: compiler.err.cant.ref.before.ctor.called: this
|
||||
EarlyAssignments.java:119:17: compiler.err.cant.ref.before.ctor.called: x
|
||||
EarlyAssignments.java:124:22: compiler.err.cant.ref.before.ctor.called: x
|
||||
EarlyAssignments.java:129:29: compiler.err.cant.ref.before.ctor.called: x
|
||||
EarlyAssignments.java:134:17: compiler.err.cant.ref.before.ctor.called: super
|
||||
EarlyAssignments.java:139:23: compiler.err.cant.ref.before.ctor.called: this
|
||||
EarlyAssignments.java:148:13: compiler.err.cant.assign.initialized.before.ctor.called: x
|
||||
EarlyAssignments.java:157:13: compiler.err.cant.assign.val.to.var: final, x
|
||||
- compiler.note.preview.filename: EarlyAssignments.java, DEFAULT
|
||||
- compiler.note.preview.recompile
|
||||
25 errors
|
19
test/langtools/tools/javac/SuperInit/EarlyLocalClass.java
Normal file
19
test/langtools/tools/javac/SuperInit/EarlyLocalClass.java
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 8325805
|
||||
* @summary Verify local class in early construction context has no outer instance
|
||||
* @compile/fail/ref=EarlyLocalClass.out -XDrawDiagnostics EarlyLocalClass.java
|
||||
* @enablePreview
|
||||
*/
|
||||
public class EarlyLocalClass {
|
||||
EarlyLocalClass() {
|
||||
class Local {
|
||||
void foo() {
|
||||
EarlyLocalClass.this.hashCode(); // this should FAIL
|
||||
}
|
||||
}
|
||||
new Local(); // this is OK
|
||||
super();
|
||||
new Local(); // this is OK
|
||||
}
|
||||
}
|
4
test/langtools/tools/javac/SuperInit/EarlyLocalClass.out
Normal file
4
test/langtools/tools/javac/SuperInit/EarlyLocalClass.out
Normal file
@ -0,0 +1,4 @@
|
||||
EarlyLocalClass.java:12:32: compiler.err.no.encl.instance.of.type.in.scope: EarlyLocalClass
|
||||
- compiler.note.preview.filename: EarlyLocalClass.java, DEFAULT
|
||||
- compiler.note.preview.recompile
|
||||
1 error
|
@ -91,7 +91,7 @@ public class SuperInitFails extends AtomicReference<Object> implements Iterable<
|
||||
}
|
||||
|
||||
public SuperInitFails(short[] x) {
|
||||
this.x = x.length; // this should FAIL
|
||||
this.x++; // this should FAIL
|
||||
super();
|
||||
}
|
||||
|
||||
@ -145,16 +145,6 @@ public class SuperInitFails extends AtomicReference<Object> implements Iterable<
|
||||
return null;
|
||||
}
|
||||
|
||||
public SuperInitFails(short[][] x) {
|
||||
class Foo {
|
||||
Foo() {
|
||||
SuperInitFails.this.hashCode();
|
||||
}
|
||||
};
|
||||
new Foo(); // this should FAIL
|
||||
super();
|
||||
}
|
||||
|
||||
public SuperInitFails(float[][] x) {
|
||||
Runnable r = () -> {
|
||||
super(); // this should FAIL
|
||||
@ -168,4 +158,32 @@ public class SuperInitFails extends AtomicReference<Object> implements Iterable<
|
||||
public SuperInitFails(long[][] z) {
|
||||
super(new Inner1()); // this should FAIL
|
||||
}
|
||||
|
||||
public static class Inner2 {
|
||||
int x;
|
||||
}
|
||||
public static class Inner3 extends Inner2 {
|
||||
int y;
|
||||
Inner3(byte z) {
|
||||
x = z; // this should FAIL
|
||||
super();
|
||||
}
|
||||
Inner3(short z) {
|
||||
this.x = z; // this should FAIL
|
||||
super();
|
||||
}
|
||||
Inner3(char z) {
|
||||
Inner3.this.x = z; // this should FAIL
|
||||
super();
|
||||
}
|
||||
Inner3(int z) {
|
||||
super.x = z; // this should FAIL
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
public SuperInitFails(double[][] x) {
|
||||
Runnable r = () -> this.x = 7; // this should FAIL
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
@ -12,9 +12,13 @@ SuperInitFails.java:119:22: compiler.err.call.must.only.appear.in.ctor
|
||||
SuperInitFails.java:125:9: compiler.err.cant.ref.before.ctor.called: this
|
||||
SuperInitFails.java:133:9: compiler.err.non.canonical.constructor.invoke.another.constructor: SuperInitFails.Record1
|
||||
SuperInitFails.java:138:9: compiler.err.non.canonical.constructor.invoke.another.constructor: SuperInitFails.Record2
|
||||
SuperInitFails.java:154:9: compiler.err.cant.ref.before.ctor.called: this
|
||||
SuperInitFails.java:165:31: compiler.err.cant.ref.before.ctor.called: x
|
||||
SuperInitFails.java:169:15: compiler.err.cant.ref.before.ctor.called: this
|
||||
SuperInitFails.java:155:31: compiler.err.cant.ref.before.ctor.called: x
|
||||
SuperInitFails.java:159:15: compiler.err.cant.ref.before.ctor.called: this
|
||||
SuperInitFails.java:168:13: compiler.err.cant.ref.before.ctor.called: x
|
||||
SuperInitFails.java:172:17: compiler.err.cant.ref.before.ctor.called: x
|
||||
SuperInitFails.java:176:24: compiler.err.cant.ref.before.ctor.called: x
|
||||
SuperInitFails.java:180:18: compiler.err.cant.ref.before.ctor.called: x
|
||||
SuperInitFails.java:186:28: compiler.err.cant.ref.before.ctor.called: this
|
||||
SuperInitFails.java:33:13: compiler.err.call.must.only.appear.in.ctor
|
||||
SuperInitFails.java:37:14: compiler.err.call.must.only.appear.in.ctor
|
||||
SuperInitFails.java:41:14: compiler.err.call.must.only.appear.in.ctor
|
||||
@ -23,7 +27,7 @@ SuperInitFails.java:49:33: compiler.err.call.must.only.appear.in.ctor
|
||||
SuperInitFails.java:53:32: compiler.err.call.must.only.appear.in.ctor
|
||||
SuperInitFails.java:83:18: compiler.err.ctor.calls.not.allowed.here
|
||||
SuperInitFails.java:89:13: compiler.err.return.before.superclass.initialized
|
||||
SuperInitFails.java:160:18: compiler.err.ctor.calls.not.allowed.here
|
||||
SuperInitFails.java:150:18: compiler.err.ctor.calls.not.allowed.here
|
||||
- compiler.note.preview.filename: SuperInitFails.java, DEFAULT
|
||||
- compiler.note.preview.recompile
|
||||
26 errors
|
||||
30 errors
|
||||
|
@ -407,6 +407,54 @@ public class SuperInitGood {
|
||||
}
|
||||
}
|
||||
|
||||
// we allow 'this' reference prior to super() for field assignments only
|
||||
public static class Test20 {
|
||||
private int x;
|
||||
public Test20(short x) {
|
||||
x = x;
|
||||
super();
|
||||
}
|
||||
public Test20(int x) {
|
||||
this.x = x;
|
||||
super();
|
||||
}
|
||||
public Test20(char x) {
|
||||
Test20.this.x = x;
|
||||
super();
|
||||
}
|
||||
public Test20(byte y) {
|
||||
x = y;
|
||||
this((int)y);
|
||||
this.x++;
|
||||
}
|
||||
}
|
||||
|
||||
// allow creating and using local and anonymous classes before super()
|
||||
// they will not have enclosing instances though
|
||||
public static class Test21 {
|
||||
public Test21(int x) {
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
this.hashCode();
|
||||
}
|
||||
};
|
||||
r.run();
|
||||
super();
|
||||
r.run();
|
||||
}
|
||||
public Test21(float x) {
|
||||
class Foo {
|
||||
public void bar() {
|
||||
this.hashCode();
|
||||
}
|
||||
};
|
||||
new Foo().bar();
|
||||
super();
|
||||
new Foo().bar();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
new Test0();
|
||||
new Test1();
|
||||
@ -448,5 +496,8 @@ public class SuperInitGood {
|
||||
assert false : "unexpected exception: " + e;
|
||||
}
|
||||
new Test19(123);
|
||||
new Test20(123);
|
||||
new Test21((int)123);
|
||||
new Test21((float)123);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.note.preview.filename
|
||||
// key: compiler.note.preview.recompile
|
||||
// key: compiler.err.cant.assign.initialized.before.ctor.called
|
||||
// options: --enable-preview -source ${jdk.version}
|
||||
|
||||
class CantAssignInitializedBeforeCtorCalled {
|
||||
int x = 1;
|
||||
CantAssignInitializedBeforeCtorCalled() {
|
||||
x = 2;
|
||||
super();
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -21,12 +21,12 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.misc.feature.super.init
|
||||
// key: compiler.misc.feature.flexible.constructors
|
||||
// key: compiler.warn.preview.feature.use
|
||||
// options: --enable-preview -source ${jdk.version} -Xlint:preview
|
||||
|
||||
class FeatureStatementsBeforeSuper {
|
||||
FeatureStatementsBeforeSuper() {
|
||||
class FeatureFlexibleConstructors {
|
||||
FeatureFlexibleConstructors() {
|
||||
System.out.println();
|
||||
super();
|
||||
}
|
Loading…
Reference in New Issue
Block a user